All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.syndication.propono.atom.server.impl.FileBasedCollection Maven / Gradle / Ivy

Go to download

The ROME Propono subproject is a Java class library that supports publishing protocols, specifically the Atom Publishing Protocol and the legacy MetaWeblog API. Propono includes an Atom client library, Atom server framework and a Blog client that supports both Atom protocol and the MetaWeblog API.

The newest version!
/*   
 * Copyright 2007 Sun Microsystems, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package com.sun.syndication.propono.atom.server.impl;

import java.util.Iterator;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;


import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.atom.Category;
import com.sun.syndication.feed.atom.Content;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Feed;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.WireFeedInput;
import com.sun.syndication.io.WireFeedOutput;
import com.sun.syndication.io.impl.Atom10Generator;
import com.sun.syndication.io.impl.Atom10Parser;
import com.sun.syndication.propono.atom.common.Categories;
import com.sun.syndication.propono.atom.common.Collection;
import com.sun.syndication.propono.atom.common.rome.AppModule;
import com.sun.syndication.propono.atom.common.rome.AppModuleImpl;

import com.sun.syndication.propono.atom.server.AtomException;
import com.sun.syndication.propono.atom.server.AtomMediaResource;
import com.sun.syndication.propono.atom.server.AtomNotFoundException;
import com.sun.syndication.propono.utils.Utilities;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * File based Atom collection implementation. This is the heart of the 
 * file-based Atom service implementation. It provides methods for adding, 
 * getting updating and deleting Atom entries and media entries.
 */
public class FileBasedCollection extends Collection {
    private static Log log =
            LogFactory.getFactory().getInstance(FileBasedCollection.class);
    
    private String handle = null;
    private String singular = null;
    private String collection = null;
    
    private boolean inlineCats = false;
    private String[] catNames = null;

    private boolean relativeURIs = false;
    private String contextURI = null; 
    private String contextPath = null;
    private String servletPath = null;
    private String baseDir = null;
    
    private static final String FEED_TYPE = "atom_1.0";

    /**
     * Construct by providing title (plain text, no HTML), a workspace handle,
     * a plural collection name (e.g. entries), a singular collection name
     * (e.g. entry), the base directory for file storage, the content-type
     * range accepted by the collection and the root Atom protocol URI for the
     * service.
     * @param title        Title of collection (plain text, no HTML)
     * @param handle       Workspace handle
     * @param collection   Collection handle, plural
     * @param singular     Collection handle, singular
     * @param accept       Content type range accepted by collection
     * @param inlineCats   True for inline categories
     * @param catNames     Category names for this workspace
     * @param baseDir      Base directory for file storage
     * @param relativeURIs True for relative URIs
     * @param contextURI   Absolute URI of context that hosts APP service
     * @param contextPath  Context path of APP service (e.g. "/sample-atomserver")
     * @param servletPath  Servlet path of APP service (e.g. "/app")
     */
    public FileBasedCollection(
        String title,
        String handle, 
        String collection, 
        String singular, 
        String accept,
        boolean inlineCats, 
        String[] catNames,
        boolean relativeURIs,
        String contextURI,
        String contextPath,
        String servletPath,
        String baseDir) {       
        super(title, "text", 
                relativeURIs 
                ? servletPath.substring(1) + "/" + handle + "/" + collection
                : contextURI + servletPath + "/" + handle + "/" + collection);
        
        this.handle = handle;
        this.collection = collection;
        this.singular = singular;
        this.inlineCats = inlineCats;
        this.catNames = catNames;
        this.baseDir = baseDir;
        this.relativeURIs = relativeURIs;
        this.contextURI = contextURI;
        this.contextPath = contextPath;
        this.servletPath = servletPath;
        
        addAccept(accept);
    }
    
    /**
     * Get feed document representing collection.
     * @throws com.sun.syndication.propono.atom.server.AtomException On error retrieving feed file.
     * @return Atom Feed representing collection.
     */
    public Feed getFeedDocument() throws AtomException {
        InputStream in = null;        
        synchronized(FileStore.getFileStore()) {
            in = FileStore.getFileStore().getFileInputStream(getFeedPath());            
            if (in == null) {
                in = createDefaultFeedDocument(contextURI + servletPath + "/" + handle + "/" + collection);
            }
        }        
        try {
            WireFeedInput input = new WireFeedInput();
            WireFeed wireFeed = input.build(new InputStreamReader(in, "UTF-8"));
            return (Feed)wireFeed;
        } catch (Exception ex) {
            throw new AtomException(ex);
        } 
    }   

    /**
     * Get list of one Categories object containing categories allowed by collection.
     * @param inline True if Categories object should contain collection of 
     *                in-line Categories objects or false if it should set the 
     *                Href for out-of-line categories.
     */
    public List getCategories(boolean inline) {
        Categories cats = new Categories();
        cats.setFixed(true);
        cats.setScheme(contextURI + "/" + handle + "/" + singular);
        if (inline) {
            for (int i=0; i[collection-plural]/[entryid]/media/[entryid].
     * An Atom entry will be created to store metadata for the entry and it will exist 
     * at the path [collection-plural]/[entryid]/entry.xml.
     * The entry will be added to the collection's feed in [collection-plural]/feed.xml.
     * @param entry Entry object
     * @param slug String to be used in file-name
     * @param is Source of media data
     * @throws java.lang.Exception On Error
     * @return Location URI of entry
     */
    public String addMediaEntry(Entry entry, String slug, InputStream is) throws Exception {
        synchronized (FileStore.getFileStore()) {            

            // Save media file temp file
            Content content = (Content)entry.getContents().get(0);
            if (entry.getTitle() == null) {
                entry.setTitle(slug);
            }
            String fileName = createFileName((slug != null) ? slug : entry.getTitle(), content.getType());                 
            File tempFile = File.createTempFile(fileName, "tmp");
            FileOutputStream fos = new FileOutputStream(tempFile);
            Utilities.copyInputToOutput(is, fos);
            fos.close();

            // Save media file
            FileInputStream fis = new FileInputStream(tempFile);
            saveMediaFile(fileName, content.getType(), tempFile.length(), fis);
            fis.close();
            File resourceFile = new File(getEntryMediaPath(fileName));

            // Create media-link entry
            updateTimestamps(entry); 

            // Save media-link entry
            String entryPath = getEntryPath(fileName);  
            OutputStream os = FileStore.getFileStore().getFileOutputStream(entryPath);
            updateMediaEntryAppLinks(entry, resourceFile.getName(), true);
            Atom10Generator.serializeEntry(entry, new OutputStreamWriter(os, "UTF-8"));
            os.flush();
            os.close();

            // Update feed with new entry
            Feed f = getFeedDocument();
            updateMediaEntryAppLinks(entry, resourceFile.getName(), false);
            updateFeedDocumentWithNewEntry(f, entry);

            return getEntryEditURI(fileName, false, true);
        }
    }
    
    /**
     * Get an entry from the collection.
     * @param fsid Internal ID of entry to be returned
     * @throws java.lang.Exception On error
     * @return Entry specified by fileName/ID
     */
    public Entry getEntry(String fsid) throws Exception {
        if (fsid.endsWith(".media-link")) {
            fsid = fsid.substring(0, fsid.length() - ".media-link".length());
        }

        String entryPath = getEntryPath(fsid); 

        checkExistence(entryPath);
        InputStream in = FileStore.getFileStore().getFileInputStream(entryPath);

        final Entry entry;
        String filePath = getEntryMediaPath(fsid);                    
        File resource = new File(fsid);
        if (resource.exists()) {
            entry = loadAtomResourceEntry(in, resource);
            updateMediaEntryAppLinks(entry, fsid, true);
        } else {
            entry = loadAtomEntry(in);
            updateEntryAppLinks(entry, fsid, true);
        }
        return entry;
    }
    
    /**
     * Get media resource wrapping a file.
     */
    public AtomMediaResource getMediaResource(String fileName) throws Exception {
        String filePath = getEntryMediaPath(fileName);                    
        File resource = new File(filePath);
        return new AtomMediaResource(resource);
    }
    
    /**
     * Update an entry in the collection.
     * @param entry Updated entry to be stored
     * @param fsid Internal ID of entry
     * @throws java.lang.Exception On error
     */
    public void updateEntry(Entry entry, String fsid) throws Exception {
        synchronized (FileStore.getFileStore()) {            

            Feed f = getFeedDocument();

            if (fsid.endsWith(".media-link")) {
                fsid = fsid.substring(0, fsid.length() - ".media-link".length());
            }

            updateTimestamps(entry);

            updateEntryAppLinks(entry, fsid, false);
            updateFeedDocumentWithExistingEntry(f, entry);

            String entryPath = getEntryPath(fsid);
            OutputStream os = FileStore.getFileStore().getFileOutputStream(entryPath);
            updateEntryAppLinks(entry, fsid, true);
            Atom10Generator.serializeEntry(entry, new OutputStreamWriter(os, "UTF-8"));
            os.flush();
            os.close();
        }
    }
    
    /**
     * Update media associated with a media-link entry.
     * @param fileName Internal ID of entry being updated
     * @param contentType Content type of data
     * @param is Source of updated data
     * @throws java.lang.Exception On error
     * @return Updated Entry as it exists on server
     */
    public Entry updateMediaEntry(String fileName, String contentType, InputStream is) throws Exception {
        synchronized (FileStore.getFileStore()) {            

            File tempFile = File.createTempFile(fileName, "tmp");
            FileOutputStream fos = new FileOutputStream(tempFile);
            Utilities.copyInputToOutput(is, fos);
            fos.close();

            // Update media file
            FileInputStream fis = new FileInputStream(tempFile);
            saveMediaFile(fileName, contentType, tempFile.length(), fis);
            fis.close();
            File resourceFile = new File(getEntryMediaPath(fileName));

            // Load media-link entry to return
            String entryPath = getEntryPath(fileName);
            InputStream in = FileStore.getFileStore().getFileInputStream(entryPath);
            Entry atomEntry = loadAtomResourceEntry(in, resourceFile);

            updateTimestamps(atomEntry);
            updateMediaEntryAppLinks(atomEntry, fileName, false);

            // Update feed with new entry
            Feed f = getFeedDocument();
            updateFeedDocumentWithExistingEntry(f, atomEntry);

            // Save updated media-link entry
            OutputStream os = FileStore.getFileStore().getFileOutputStream(entryPath);
            updateMediaEntryAppLinks(atomEntry, fileName, true);
            Atom10Generator.serializeEntry(atomEntry, new OutputStreamWriter(os, "UTF-8"));
            os.flush();
            os.close();  

            return atomEntry;
        }
    }
    
    /**
     * Delete an entry and any associated media file.
     * @param fsid Internal ID of entry
     * @throws java.lang.Exception On error
     */
    public void deleteEntry(String fsid) throws Exception {
        synchronized (FileStore.getFileStore()) {

            // Remove entry from Feed
            Feed feed = getFeedDocument();
            updateFeedDocumentRemovingEntry(feed, fsid);

            String entryFilePath = this.getEntryPath(fsid);
            FileStore.getFileStore().deleteFile(entryFilePath);
            
            String entryMediaPath = this.getEntryMediaPath(fsid);
            if (entryMediaPath != null) {
                FileStore.getFileStore().deleteFile(entryMediaPath);
            }
            
            String entryDirPath = getEntryDirPath(fsid);
            FileStore.getFileStore().deleteDirectory(entryDirPath); 
            
            try {Thread.sleep(500L);}catch(Exception ignored){}
        }
    }
    
    private void updateFeedDocumentWithNewEntry(Feed f, Entry e) throws AtomException {
        boolean inserted = false;
        for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy