001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.lenya.cms.cocoon.source;
020:
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.net.MalformedURLException;
025: import java.util.Iterator;
026:
027: import javax.xml.parsers.ParserConfigurationException;
028: import javax.xml.transform.TransformerConfigurationException;
029: import javax.xml.transform.TransformerException;
030:
031: import org.apache.avalon.framework.service.ServiceException;
032: import org.apache.avalon.framework.service.ServiceManager;
033: import org.apache.commons.io.IOUtils;
034: import org.apache.commons.io.output.ByteArrayOutputStream;
035: import org.apache.excalibur.source.ModifiableSource;
036: import org.apache.excalibur.source.ModifiableTraversableSource;
037: import org.apache.excalibur.source.Source;
038: import org.apache.excalibur.source.SourceException;
039: import org.apache.excalibur.source.SourceNotFoundException;
040: import org.apache.excalibur.source.SourceResolver;
041: import org.apache.lenya.cms.repository.RepositoryException;
042: import org.apache.lenya.xml.DocumentHelper;
043: import org.w3c.dom.Document;
044: import org.xml.sax.SAXException;
045:
046: /**
047: * @version $Id: SourceUtil.java 507914 2007-02-15 12:15:30Z andreas $
048: */
049: public final class SourceUtil {
050:
051: /**
052: * <p>
053: * Copies one Source to another using a source buffer i.e. the source Source
054: * is buffered before it is copied to its final destination.
055: * </p>
056: * <p>
057: * The optional buffering is sometimes useful, if the source Source somehow
058: * depends on the destination Source. This situation may occur e.g. if
059: * source Source is a Cocoon pipeline.
060: * </p>
061: * <p>
062: * <em>NOTE:</em> o.a.e..s.SourceUtil.copy does not close streams on an
063: * exception!!
064: * </p>
065: * @param source
066: * @param destination
067: * @param useBuffer If true, the source data will be read into a buffer
068: * before it is written to the final destination.
069: * @throws IOException If an error occures.
070: */
071: public static void copy(Source source,
072: ModifiableSource destination, boolean useBuffer)
073: throws IOException {
074: InputStream sourceInputStream = null;
075: OutputStream destOutputStream = null;
076: try {
077: sourceInputStream = source.getInputStream();
078: destOutputStream = destination.getOutputStream();
079:
080: if (useBuffer) {
081: final ByteArrayOutputStream sourceBos = new ByteArrayOutputStream();
082: IOUtils.copy(sourceInputStream, sourceBos);
083: IOUtils
084: .write(sourceBos.toByteArray(),
085: destOutputStream);
086: } else {
087: IOUtils.copy(sourceInputStream, destOutputStream);
088: }
089: } finally {
090: if (destOutputStream != null) {
091: destOutputStream.flush();
092: destOutputStream.close();
093: }
094: if (sourceInputStream != null) {
095: sourceInputStream.close();
096: }
097: }
098: }
099:
100: /**
101: * Copies one Source to another. The source Source is optionally buffered.
102: * @param resolver The SourceResolver to use for lookin up Sources.
103: * @param sourceUri The source to be copied.
104: * @param destUri The URI to copy to.
105: * @param useBuffer If true, the source Source is buffered before copied to
106: * the final destination.
107: * @throws IOException If an error occures.
108: * @throws SourceException If the destination is not modifiable.
109: * @see #copy(Source, ModifiableSource, boolean)
110: */
111: public static void copy(SourceResolver resolver, String sourceUri,
112: String destUri, boolean useBuffer) throws IOException,
113: SourceException {
114: Source source = null;
115: Source dest = null;
116: try {
117: source = resolver.resolveURI(sourceUri);
118: dest = resolver.resolveURI(destUri);
119:
120: if (!(dest instanceof ModifiableSource))
121: throw new SourceException("Destination '"
122: + dest.getURI() + "' is not modifiable.");
123:
124: copy(source, (ModifiableSource) dest, useBuffer);
125: } finally {
126: if (source != null)
127: resolver.release(source);
128: if (dest != null)
129: resolver.release(dest);
130: }
131: }
132:
133: /**
134: * Copies a Source without buffering.
135: * @param resolver A SourceResolver instance.
136: * @param sourceUri The source URI to copy from.
137: * @param destUri The destination URI to copy to.
138: * @throws IOException If an error occures.
139: * @see #copy(SourceResolver, String, String, boolean)
140: */
141: public static void copy(SourceResolver resolver, String sourceUri,
142: String destUri) throws IOException {
143: copy(resolver, sourceUri, destUri, false);
144: }
145:
146: /**
147: * Copies a Source without buffering.
148: * @param manager A service manager.
149: * @param sourceUri The source URI to copy from.
150: * @param destUri The destination URI to copy to.
151: * @throws IOException If an error occures.
152: * @throws ServiceException
153: * @see #copy(SourceResolver, String, String, boolean)
154: */
155: public static void copy(ServiceManager manager, String sourceUri,
156: String destUri) throws IOException, ServiceException {
157: SourceResolver resolver = null;
158: try {
159: resolver = (SourceResolver) manager
160: .lookup(SourceResolver.ROLE);
161: copy(resolver, sourceUri, destUri, false);
162: } finally {
163: if (resolver != null) {
164: manager.release(resolver);
165: }
166: }
167: }
168:
169: /**
170: * Reads a DOM from a source.
171: * @param sourceUri The source URI.
172: * @param manager The service manager.
173: * @return A document or <code>null</code> if the source does not exist.
174: * @throws ServiceException if an error occurs.
175: * @throws SourceNotFoundException if an error occurs.
176: * @throws ParserConfigurationException if an error occurs.
177: * @throws SAXException if an error occurs.
178: * @throws IOException if an error occurs.
179: */
180: public static Document readDOM(String sourceUri,
181: ServiceManager manager) throws ServiceException,
182: SourceNotFoundException, ParserConfigurationException,
183: SAXException, IOException {
184: SourceResolver resolver = null;
185: Source source = null;
186: Document document = null;
187: try {
188:
189: resolver = (SourceResolver) manager
190: .lookup(SourceResolver.ROLE);
191: source = resolver.resolveURI(sourceUri);
192:
193: if (source.exists()) {
194: document = DocumentHelper.readDocument(source
195: .getInputStream());
196: }
197: } finally {
198: if (resolver != null) {
199: if (source != null) {
200: resolver.release(source);
201: }
202: manager.release(resolver);
203: }
204: }
205: return document;
206: }
207:
208: /**
209: * Writes a DOM to a source.
210: * @param document The document.
211: * @param sourceUri The source URI.
212: * @param manager The service manager.
213: * @throws TransformerConfigurationException if an error occurs.
214: * @throws TransformerException if an error occurs.
215: * @throws ServiceException if the source resolver could not be obtained.
216: * @throws MalformedURLException if the source URI is not valid.
217: * @throws IOException if an error occurs.
218: */
219: public static void writeDOM(Document document, String sourceUri,
220: ServiceManager manager)
221: throws TransformerConfigurationException,
222: TransformerException, ServiceException,
223: MalformedURLException, IOException {
224: SourceResolver resolver = null;
225: ModifiableSource source = null;
226: try {
227:
228: resolver = (SourceResolver) manager
229: .lookup(SourceResolver.ROLE);
230: source = (ModifiableSource) resolver.resolveURI(sourceUri);
231:
232: OutputStream oStream = source.getOutputStream();
233: writeDOM(document, oStream);
234: } finally {
235: if (resolver != null) {
236: if (source != null) {
237: resolver.release(source);
238: }
239: manager.release(resolver);
240: }
241: }
242: }
243:
244: /**
245: * @param document The XML document.
246: * @param oStream The output stream.
247: * @throws TransformerConfigurationException if an error occurs.
248: * @throws TransformerException if an error occurs.
249: * @throws IOException if an error occurs.
250: */
251: public static void writeDOM(Document document, OutputStream oStream)
252: throws TransformerConfigurationException,
253: TransformerException, IOException {
254: DocumentHelper.writeDocument(document, oStream);
255: if (oStream != null) {
256: oStream.flush();
257: try {
258: oStream.close();
259: } catch (Throwable t) {
260: throw new RuntimeException(
261: "Could not write document: ", t);
262: }
263: }
264: }
265:
266: /**
267: * Deletes a source if it exists.
268: * @param sourceUri The source URI.
269: * @param manager The service manager.
270: * @throws ServiceException if an error occurs.
271: * @throws MalformedURLException if an error occurs.
272: * @throws IOException if an error occurs.
273: */
274: public static void delete(String sourceUri, ServiceManager manager)
275: throws ServiceException, MalformedURLException, IOException {
276: SourceResolver resolver = null;
277: ModifiableTraversableSource source = null;
278: try {
279:
280: resolver = (SourceResolver) manager
281: .lookup(SourceResolver.ROLE);
282: source = (ModifiableTraversableSource) resolver
283: .resolveURI(sourceUri);
284: if (source.exists()) {
285: source.delete();
286: }
287:
288: } finally {
289: if (resolver != null) {
290: if (source != null) {
291: resolver.release(source);
292: }
293: manager.release(resolver);
294: }
295: }
296: }
297:
298: /**
299: * Deletes all empty collections in a subtree.
300: * @param sourceUri The root source URI.
301: * @param manager The service manager.
302: * @throws ServiceException
303: * @throws MalformedURLException
304: * @throws IOException
305: */
306: public static void deleteEmptyCollections(String sourceUri,
307: ServiceManager manager) throws ServiceException,
308: MalformedURLException, IOException {
309: SourceResolver resolver = null;
310: ModifiableTraversableSource source = null;
311: try {
312: resolver = (SourceResolver) manager
313: .lookup(SourceResolver.ROLE);
314: source = (ModifiableTraversableSource) resolver
315: .resolveURI(sourceUri);
316: if (source.isCollection()) {
317: for (Iterator i = source.getChildren().iterator(); i
318: .hasNext();) {
319: ModifiableTraversableSource child = (ModifiableTraversableSource) i
320: .next();
321: deleteEmptyCollections(child.getURI(), manager);
322: }
323: if (source.getChildren().size() == 0) {
324: source.delete();
325: }
326: }
327: } finally {
328: if (resolver != null) {
329: if (source != null) {
330: resolver.release(source);
331: }
332: manager.release(resolver);
333: }
334: }
335: }
336:
337: /**
338: * Checks if a source exists.
339: * @param sourceUri The source URI.
340: * @param manager The service manager.
341: * @return A boolean value.
342: * @throws ServiceException if an error occurs.
343: * @throws MalformedURLException if an error occurs.
344: * @throws IOException if an error occurs.
345: */
346: public static boolean exists(String sourceUri,
347: ServiceManager manager) throws ServiceException,
348: MalformedURLException, IOException {
349: SourceResolver resolver = null;
350: Source source = null;
351: try {
352:
353: resolver = (SourceResolver) manager
354: .lookup(SourceResolver.ROLE);
355: source = resolver.resolveURI(sourceUri);
356:
357: return source.exists();
358: } finally {
359: if (resolver != null) {
360: if (source != null) {
361: resolver.release(source);
362: }
363: manager.release(resolver);
364: }
365: }
366: }
367:
368: /**
369: * Returns the last modification date of a source.
370: * @param sourceUri The source URI.
371: * @param manager The service manager.
372: * @return A long value.
373: * @throws ServiceException if an error occurs.
374: * @throws MalformedURLException if an error occurs.
375: * @throws IOException if an error occurs.
376: */
377: public static long getLastModified(String sourceUri,
378: ServiceManager manager) throws ServiceException,
379: MalformedURLException, IOException {
380: SourceResolver resolver = null;
381: Source source = null;
382: try {
383:
384: resolver = (SourceResolver) manager
385: .lookup(SourceResolver.ROLE);
386: source = resolver.resolveURI(sourceUri);
387:
388: return source.getLastModified();
389: } finally {
390: if (resolver != null) {
391: if (source != null) {
392: resolver.release(source);
393: }
394: manager.release(resolver);
395: }
396: }
397: }
398:
399: /**
400: * Checks out a repository source.
401: * @param sourceUri The source URI.
402: * @param manager The service manager.
403: * @throws RepositoryException If an error occurs.
404: * @throws ServiceException If an error occurs.
405: * @throws MalformedURLException If an error occurs.
406: * @throws IOException If an error occurs.
407: */
408: public static void checkout(String sourceUri, ServiceManager manager)
409: throws RepositoryException, ServiceException,
410: MalformedURLException, IOException {
411: SourceResolver resolver = null;
412: RepositorySource source = null;
413: try {
414:
415: resolver = (SourceResolver) manager
416: .lookup(SourceResolver.ROLE);
417: source = (RepositorySource) resolver.resolveURI(sourceUri);
418:
419: source.getNode().checkout();
420:
421: } finally {
422: if (resolver != null) {
423: if (source != null) {
424: resolver.release(source);
425: }
426: manager.release(resolver);
427: }
428: }
429: }
430:
431: /**
432: * Checks in a transactionable source.
433: * @param sourceUri The source URI.
434: * @param manager The service manager.
435: * @throws RepositoryException If an error occurs.
436: * @throws ServiceException If an error occurs.
437: * @throws MalformedURLException If an error occurs.
438: * @throws IOException If an error occurs.
439: */
440: public static void checkin(String sourceUri, ServiceManager manager)
441: throws RepositoryException, ServiceException,
442: MalformedURLException, IOException {
443: SourceResolver resolver = null;
444: RepositorySource source = null;
445: try {
446:
447: resolver = (SourceResolver) manager
448: .lookup(SourceResolver.ROLE);
449: source = (RepositorySource) resolver.resolveURI(sourceUri);
450:
451: source.getNode().checkin();
452:
453: } finally {
454: if (resolver != null) {
455: if (source != null) {
456: resolver.release(source);
457: }
458: manager.release(resolver);
459: }
460: }
461: }
462:
463: /**
464: * Locks a transactionable source.
465: * @param sourceUri The source URI.
466: * @param manager The service manager.
467: * @throws RepositoryException If an error occurs.
468: */
469: public static void lock(String sourceUri, ServiceManager manager)
470: throws RepositoryException {
471: SourceResolver resolver = null;
472: RepositorySource source = null;
473: try {
474:
475: resolver = (SourceResolver) manager
476: .lookup(SourceResolver.ROLE);
477: source = (RepositorySource) resolver.resolveURI(sourceUri);
478:
479: source.getNode().lock();
480:
481: } catch (RepositoryException e) {
482: throw e;
483: } catch (Exception e) {
484: throw new RepositoryException(e);
485: } finally {
486: if (resolver != null) {
487: if (source != null) {
488: resolver.release(source);
489: }
490: manager.release(resolver);
491: }
492: }
493: }
494:
495: /**
496: * Unlocks a transactionable source.
497: * @param sourceUri The source URI.
498: * @param manager The service manager.
499: * @throws RepositoryException If an error occurs.
500: */
501: public static void unlock(String sourceUri, ServiceManager manager)
502: throws RepositoryException {
503: SourceResolver resolver = null;
504: RepositorySource source = null;
505: try {
506:
507: resolver = (SourceResolver) manager
508: .lookup(SourceResolver.ROLE);
509: source = (RepositorySource) resolver.resolveURI(sourceUri);
510:
511: source.getNode().unlock();
512:
513: } catch (RepositoryException e) {
514: throw e;
515: } catch (Exception e) {
516: throw new RepositoryException(e);
517: } finally {
518: if (resolver != null) {
519: if (source != null) {
520: resolver.release(source);
521: }
522: manager.release(resolver);
523: }
524: }
525: }
526:
527: /**
528: * Registers a source as dirty.
529: * @param sourceUri The source URI.
530: * @param manager The service manager.
531: */
532: public static void registerDirty(String sourceUri,
533: ServiceManager manager) {
534: SourceResolver resolver = null;
535: RepositorySource source = null;
536: try {
537:
538: resolver = (SourceResolver) manager
539: .lookup(SourceResolver.ROLE);
540: source = (RepositorySource) resolver.resolveURI(sourceUri);
541: source.getNode().registerDirty();
542:
543: } catch (Exception e) {
544: throw new RuntimeException(e);
545: } finally {
546: if (resolver != null) {
547: if (source != null) {
548: resolver.release(source);
549: }
550: manager.release(resolver);
551: }
552: }
553: }
554:
555: /**
556: * @param sourceUri The source URI.
557: * @param manager The service manager.
558: * @return A content length.
559: * @throws ServiceException
560: * @throws MalformedURLException
561: * @throws IOException
562: */
563: public static long getContentLength(String sourceUri,
564: ServiceManager manager) throws ServiceException,
565: MalformedURLException, IOException {
566: SourceResolver resolver = null;
567: Source source = null;
568: try {
569:
570: resolver = (SourceResolver) manager
571: .lookup(SourceResolver.ROLE);
572: source = resolver.resolveURI(sourceUri);
573:
574: return source.getContentLength();
575: } finally {
576: if (resolver != null) {
577: if (source != null) {
578: resolver.release(source);
579: }
580: manager.release(resolver);
581: }
582: }
583: }
584:
585: /**
586: * @param sourceUri The source URI.
587: * @param manager The service manager.
588: * @return A mime type.
589: * @throws ServiceException
590: * @throws IOException
591: * @throws MalformedURLException
592: */
593: public static String getMimeType(String sourceUri,
594: ServiceManager manager) throws ServiceException,
595: MalformedURLException, IOException {
596: SourceResolver resolver = null;
597: Source source = null;
598: try {
599:
600: resolver = (SourceResolver) manager
601: .lookup(SourceResolver.ROLE);
602: source = resolver.resolveURI(sourceUri);
603:
604: return source.getMimeType();
605: } finally {
606: if (resolver != null) {
607: if (source != null) {
608: resolver.release(source);
609: }
610: manager.release(resolver);
611: }
612: }
613: }
614:
615: /**
616: * @param resolver
617: * @param sourceUri
618: * @param destOutputStream
619: * @throws MalformedURLException
620: * @throws IOException
621: */
622: public static void copy(SourceResolver resolver, String sourceUri,
623: OutputStream destOutputStream)
624: throws MalformedURLException, IOException {
625: boolean useBuffer = true;
626: InputStream sourceInputStream = null;
627: Source source = null;
628: try {
629: source = resolver.resolveURI(sourceUri);
630: sourceInputStream = source.getInputStream();
631:
632: if (useBuffer) {
633: final ByteArrayOutputStream sourceBos = new ByteArrayOutputStream();
634: IOUtils.copy(sourceInputStream, sourceBos);
635: IOUtils
636: .write(sourceBos.toByteArray(),
637: destOutputStream);
638: } else {
639: IOUtils.copy(sourceInputStream, destOutputStream);
640: }
641: } finally {
642: if (destOutputStream != null) {
643: destOutputStream.flush();
644: destOutputStream.close();
645: }
646: if (sourceInputStream != null) {
647: sourceInputStream.close();
648: }
649: if (source != null) {
650: resolver.release(source);
651: }
652: }
653: }
654: }
|