Package move.

This commit is contained in:
kebernet 2011-04-01 04:58:03 +00:00
parent c1c4dd5923
commit 4a4113127b
60 changed files with 0 additions and 8851 deletions

View file

@ -1,47 +0,0 @@
/*
* 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.client;
import com.sun.syndication.propono.utils.ProponoException;
import com.sun.syndication.io.impl.Atom10Parser;
/**
* Creates AtomService or ClientCollection based on username, password and
* end-point URI of Atom protocol service.
*/
public class AtomClientFactory {
static {
Atom10Parser.setResolveURIs(true);
}
/**
* Create AtomService by reading service doc from Atom Server.
*/
public static ClientAtomService getAtomService(
String uri, AuthStrategy authStrategy) throws ProponoException {
return new ClientAtomService(uri, authStrategy);
}
/**
* Create ClientCollection bound to URI.
*/
public static ClientCollection getCollection(
String uri, AuthStrategy authStrategy) throws ProponoException {
return new ClientCollection(uri, authStrategy);
}
}

View file

@ -1,30 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.client;
import com.sun.syndication.propono.utils.ProponoException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
public interface AuthStrategy {
/**
* Add authentication credenticals, tokens, etc. to HTTP method
*/
void addAuthentication(HttpClient httpClient, HttpMethodBase method)
throws ProponoException;
}

View file

@ -1,41 +0,0 @@
/*
* Copyright 2009 Dave Johnson (Blogapps project)
*
* 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.client;
import com.sun.syndication.io.impl.Base64;
import com.sun.syndication.propono.utils.ProponoException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
public class BasicAuthStrategy implements AuthStrategy {
private String credentials;
public BasicAuthStrategy(String username, String password) {
this.credentials =
new String(new Base64().encode((username + ":" + password).getBytes()));
}
public void init() throws ProponoException {
// op-op
}
public void addAuthentication(HttpClient httpClient, HttpMethodBase method) throws ProponoException {
httpClient.getParams().setAuthenticationPreemptive(true);
String header = "Basic " + credentials;
method.setRequestHeader("Authorization", header);
}
}

View file

@ -1,138 +0,0 @@
/*
* 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.client;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.io.impl.Atom10Parser;
import com.sun.syndication.propono.utils.ProponoException;
import com.sun.syndication.propono.atom.common.AtomService;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
/**
* This class models an Atom Publising Protocol Service Document.
* It extends the common
* {@link com.sun.syndication.propono.atom.common.Collection}
* class to add a <code>getEntry()</code> method and to return
* {@link com.sun.syndication.propono.atom.client.ClientWorkspace}
* objects instead of common
* {@link com.sun.syndication.propono.atom.common.Workspace}s.
*/
public class ClientAtomService extends AtomService {
private static Log logger = LogFactory.getLog(ClientAtomService.class);
private String uri = null;
private HttpClient httpClient = null;
private AuthStrategy authStrategy = null;
/**
* Create Atom blog service instance for specified URL and user account.
* @param url End-point URL of Atom service
*/
ClientAtomService(String uri, AuthStrategy authStrategy)
throws ProponoException {
this.uri = uri;
this.authStrategy = authStrategy;
Document doc = getAtomServiceDocument();
parseAtomServiceDocument(doc);
}
/**
* Get full entry from service by entry edit URI.
*/
public ClientEntry getEntry(String uri) throws ProponoException {
GetMethod method = new GetMethod(uri);
authStrategy.addAuthentication(httpClient, method);
try {
httpClient.executeMethod(method);
if (method.getStatusCode() != 200) {
throw new ProponoException("ERROR HTTP status code=" + method.getStatusCode());
}
Entry romeEntry = Atom10Parser.parseEntry(
new InputStreamReader(method.getResponseBodyAsStream()), uri);
if (!romeEntry.isMediaEntry()) {
return new ClientEntry(this, null, romeEntry, false);
} else {
return new ClientMediaEntry(this, null, romeEntry, false);
}
} catch (Exception e) {
throw new ProponoException("ERROR: getting or parsing entry/media", e);
} finally {
method.releaseConnection();
}
}
void addAuthentication(HttpMethodBase method) throws ProponoException {
authStrategy.addAuthentication(httpClient, method);
}
AuthStrategy getAuthStrategy() {
return authStrategy;
}
private Document getAtomServiceDocument() throws ProponoException {
GetMethod method = null;
int code = -1;
try {
httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
// TODO: make connection timeout configurable
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
method = new GetMethod(uri);
authStrategy.addAuthentication(httpClient, method);
httpClient.executeMethod(method);
SAXBuilder builder = new SAXBuilder();
return builder.build(method.getResponseBodyAsStream());
} catch (Throwable t) {
String msg = "ERROR retrieving Atom Service Document, code: "+code;
logger.debug(msg, t);
throw new ProponoException(msg, t);
} finally {
if (method != null) method.releaseConnection();
}
}
/** Deserialize an Atom service XML document into an object */
private void parseAtomServiceDocument(Document document) throws ProponoException {
Element root = document.getRootElement();
List spaces = root.getChildren("workspace", AtomService.ATOM_PROTOCOL);
Iterator iter = spaces.iterator();
while (iter.hasNext()) {
Element e = (Element) iter.next();
addWorkspace(new ClientWorkspace(e, this, uri));
}
}
/**
* Package access to httpClient.
*/
HttpClient getHttpClient() {
return httpClient;
}
}

View file

@ -1,70 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.client;
import com.sun.syndication.feed.atom.Category;
import com.sun.syndication.propono.atom.common.*;
import com.sun.syndication.propono.utils.ProponoException;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.commons.httpclient.methods.GetMethod;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
/**
* Models an Atom protocol Categories element, which may contain ROME Atom
* {@link com.sun.syndication.feed.atom.Category} elements.
*/
public class ClientCategories extends Categories {
private ClientCollection clientCollection = null;
/** Load select from XML element */
public ClientCategories(Element e, ClientCollection clientCollection) throws ProponoException {
this.clientCollection = clientCollection;
parseCategoriesElement(e);
if (getHref() != null) fetchContents();
}
public void fetchContents() throws ProponoException {
GetMethod method = new GetMethod(getHrefResolved());
clientCollection.addAuthentication(method);
try {
clientCollection.getHttpClient().executeMethod(method);
if (method.getStatusCode() != 200) {
throw new ProponoException("ERROR HTTP status code=" + method.getStatusCode());
}
SAXBuilder builder = new SAXBuilder();
Document catsDoc = builder.build(
new InputStreamReader(method.getResponseBodyAsStream()));
parseCategoriesElement(catsDoc.getRootElement());
} catch (IOException ioe) {
throw new ProponoException(
"ERROR: reading out-of-line categories", ioe);
} catch (JDOMException jde) {
throw new ProponoException(
"ERROR: parsing out-of-line categories", jde);
} finally {
method.releaseConnection();
}
}
}

View file

@ -1,217 +0,0 @@
/*
* 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.client;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.io.InputStreamReader;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.io.impl.Atom10Parser;
import com.sun.syndication.propono.atom.common.AtomService;
import com.sun.syndication.propono.atom.common.Categories;
import com.sun.syndication.propono.utils.ProponoException;
import com.sun.syndication.propono.atom.common.Collection;
import com.sun.syndication.propono.atom.common.Workspace;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.jdom.Element;
/**
* Models an Atom collection, extends Collection and adds methods for adding,
* retrieving, updateing and deleting entries.
*/
public class ClientCollection extends Collection {
static final Log logger = LogFactory.getLog(ClientCollection.class);
private List categories = new ArrayList();
private HttpClient httpClient = null;
private AuthStrategy authStrategy = null;
private boolean writable = true;
private ClientWorkspace workspace = null;
private ClientAtomService service = null;
ClientCollection(Element e, ClientWorkspace workspace, String baseURI) throws ProponoException {
super(e, baseURI);
this.workspace = workspace;
this.service = workspace.getAtomService();
this.httpClient = workspace.getAtomService().getHttpClient();
this.authStrategy = workspace.getAtomService().getAuthStrategy();
parseCollectionElement(e);
}
ClientCollection(String href, AuthStrategy authStrategy) throws ProponoException {
super("Standalone connection", "text", href);
this.authStrategy = authStrategy;
try {
httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
// TODO: make connection timeout configurable
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
} catch (Throwable t) {
throw new ProponoException("ERROR creating HTTPClient", t);
}
}
void addAuthentication(HttpMethodBase method) throws ProponoException {
authStrategy.addAuthentication(httpClient, method);
}
/**
* Package access to httpClient to allow use by ClientEntry and ClientMediaEntry.
*/
HttpClient getHttpClient() {
return httpClient;
}
/**
* Get iterator over entries in this collection. Entries returned are
* considered to be partial entries cannot be saved/updated.
*/
public Iterator getEntries() throws ProponoException {
return new EntryIterator(this);
}
/**
* Get full entry specified by entry edit URI.
* Note that entry may or may not be associated with this collection.
* @return ClientEntry or ClientMediaEntry specified by URI.
*/
public ClientEntry getEntry(String uri) throws ProponoException {
GetMethod method = new GetMethod(uri);
authStrategy.addAuthentication(httpClient, method);
try {
httpClient.executeMethod(method);
if (method.getStatusCode() != 200) {
throw new ProponoException("ERROR HTTP status code=" + method.getStatusCode());
}
Entry romeEntry = Atom10Parser.parseEntry(
new InputStreamReader(method.getResponseBodyAsStream()), uri);
if (!romeEntry.isMediaEntry()) {
return new ClientEntry(service, this, romeEntry, false);
} else {
return new ClientMediaEntry(service, this, romeEntry, false);
}
} catch (Exception e) {
throw new ProponoException("ERROR: getting or parsing entry/media, HTTP code: ", e);
} finally {
method.releaseConnection();
}
}
/**
* Get workspace or null if collection is not associated with a workspace.
*/
public Workspace getWorkspace() {
return workspace;
}
/**
* Determines if collection is writable.
*/
public boolean isWritable() {
return writable;
}
/**
* Create new entry associated with collection, but do not save to server.
* @throws ProponoException if collecton is not writable.
*/
public ClientEntry createEntry() throws ProponoException {
if (!isWritable()) throw new ProponoException("Collection is not writable");
return new ClientEntry(service, this);
}
/**
* Create new media entry assocaited with collection, but do not save.
* server. Depending on the Atom server, you may or may not be able to
* persist the properties of the entry that is returned.
* @param title Title to used for uploaded file.
* @param slug String to be used in file-name of stored file
* @param contentType MIME content-type of file.
* @param bytes Data to be uploaded as byte array.
* @throws ProponoException if collecton is not writable
*/
public ClientMediaEntry createMediaEntry(
String title, String slug, String contentType, byte[] bytes)
throws ProponoException {
if (!isWritable()) throw new ProponoException("Collection is not writable");
return new ClientMediaEntry(service, this, title, slug, contentType, bytes);
}
/**
* Create new media entry assocaited with collection, but do not save.
* server. Depending on the Atom server, you may or may not be able to.
* persist the properties of the entry that is returned.
* @param title Title to used for uploaded file.
* @param slug String to be used in file-name of stored file
* @param contentType MIME content-type of file.
* @param is Data to be uploaded as InputStream.
* @throws ProponoException if collecton is not writable
*/
public ClientMediaEntry createMediaEntry(
String title, String slug, String contentType, InputStream is)
throws ProponoException {
if (!isWritable()) throw new ProponoException("Collection is not writable");
return new ClientMediaEntry(service, this, title, slug, contentType, is);
}
/**
* Save to collection a new entry that was created by a createEntry()
* or createMediaEntry() and save it to the server.
* @param entry Entry to be saved.
* @throws ProponoException on error, if collection is not writable or if entry is partial.
*/
public void addEntry(ClientEntry entry) throws ProponoException {
if (!isWritable()) throw new ProponoException("Collection is not writable");
entry.addToCollection(this);
}
protected void parseCollectionElement(Element element) throws ProponoException {
if (workspace == null) return;
setHref(element.getAttribute("href").getValue());
Element titleElem = element.getChild("title", AtomService.ATOM_FORMAT);
if (titleElem != null) {
setTitle(titleElem.getText());
if (titleElem.getAttribute("type", AtomService.ATOM_FORMAT) != null) {
setTitleType(titleElem.getAttribute("type", AtomService.ATOM_FORMAT).getValue());
}
}
List acceptElems = element.getChildren("accept", AtomService.ATOM_PROTOCOL);
if (acceptElems != null && acceptElems.size() > 0) {
for (Iterator it = acceptElems.iterator(); it.hasNext();) {
Element acceptElem = (Element)it.next();
addAccept(acceptElem.getTextTrim());
}
}
// Loop to parse <app:categories> element to Categories objects
List catsElems = element.getChildren("categories", AtomService.ATOM_PROTOCOL);
for (Iterator catsIter = catsElems.iterator(); catsIter.hasNext();) {
Element catsElem = (Element) catsIter.next();
Categories cats = new ClientCategories(catsElem, this);
addCategories(cats);
}
}
}

View file

@ -1,259 +0,0 @@
/*
* 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.client;
import com.sun.syndication.feed.atom.Content;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.io.impl.Atom10Generator;
import com.sun.syndication.io.impl.Atom10Parser;
import com.sun.syndication.propono.utils.ProponoException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sun.syndication.propono.utils.Utilities;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.methods.PostMethod;
/**
* Client implementation of Atom entry, extends ROME Entry to add methods for
* easily getting/setting content, updating and removing the entry from the server.
*/
public class ClientEntry extends Entry {
private static final Log logger = LogFactory.getLog(ClientEntry.class);
boolean partial = false;
private ClientAtomService service = null;
private ClientCollection collection = null;
public ClientEntry(ClientAtomService service, ClientCollection collection) {
super();
this.service = service;
this.collection = collection;
}
public ClientEntry(ClientAtomService service, ClientCollection collection,
Entry entry, boolean partial) throws ProponoException {
super();
this.service = service;
this.collection = collection;
this.partial = partial;
try {
BeanUtils.copyProperties(this, entry);
} catch (Exception e) {
throw new ProponoException("ERROR: copying fields from ROME entry", e);
}
}
/**
* Set content of entry.
* @param contentString content string.
* @param type Must be "text" for plain text, "html" for escaped HTML,
* "xhtml" for XHTML or a valid MIME content-type.
*/
public void setContent(String contentString, String type) {
Content newContent = new Content();
newContent.setType(type == null ? Content.HTML : type);
newContent.setValue(contentString);
ArrayList contents = new ArrayList();
contents.add(newContent);
setContents(contents);
}
/**
* Convenience method to set first content object in content collection.
* Atom 1.0 allows only one content element per entry.
*/
public void setContent(Content c) {
ArrayList contents = new ArrayList();
contents.add(c);
setContents(contents);
}
/**
* Convenience method to get first content object in content collection.
* Atom 1.0 allows only one content element per entry.
*/
public Content getContent() {
if (getContents() != null && getContents().size() > 0) {
Content c = (Content)getContents().get(0);
return c;
}
return null;
}
/**
* Determines if entries are equal based on edit URI.
*/
public boolean equals(Object o) {
if (o instanceof ClientEntry) {
ClientEntry other = (ClientEntry)o;
if (other.getEditURI() != null && getEditURI() != null) {
return other.getEditURI().equals(getEditURI());
}
}
return false;
}
/**
* Update entry by posting new representation of entry to server.
* Note that you should not attempt to update entries that you get from
* iterating over a collection they may be "partial" entries. If you want
* to update an entry, you must get it via one of the <code>getEntry()</code>
* methods in
* {@link com.sun.syndication.propono.atom.common.Collection} or
* {@link com.sun.syndication.propono.atom.common.AtomService}.
* @throws ProponoException If entry is a "partial" entry.
*/
public void update() throws ProponoException {
if (partial) throw new ProponoException("ERROR: attempt to update partial entry");
EntityEnclosingMethod method = new PutMethod(getEditURI());
addAuthentication(method);
StringWriter sw = new StringWriter();
int code = -1;
try {
Atom10Generator.serializeEntry(this, sw);
method.setRequestEntity(new StringRequestEntity(sw.toString()));
method.setRequestHeader(
"Content-type", "application/atom+xml; charset=utf-8");
getHttpClient().executeMethod(method);
InputStream is = method.getResponseBodyAsStream();
if (method.getStatusCode() != 200 && method.getStatusCode() != 201) {
throw new ProponoException(
"ERROR HTTP status=" + method.getStatusCode() + " : " + Utilities.streamToString(is));
}
} catch (Exception e) {
String msg = "ERROR: updating entry, HTTP code: " + code;
logger.debug(msg, e);
throw new ProponoException(msg, e);
} finally {
method.releaseConnection();
}
}
/**
* Remove entry from server.
*/
public void remove() throws ProponoException {
if (getEditURI() == null) {
throw new ProponoException("ERROR: cannot delete unsaved entry");
}
DeleteMethod method = new DeleteMethod(getEditURI());
addAuthentication(method);
try {
getHttpClient().executeMethod(method);
} catch (IOException ex) {
throw new ProponoException("ERROR: removing entry, HTTP code", ex);
} finally {
method.releaseConnection();
}
}
void setCollection(ClientCollection collection) {
this.collection = collection;
}
ClientCollection getCollection() {
return collection;
}
/**
* Get the URI that can be used to edit the entry via HTTP PUT or DELETE.
*/
public String getEditURI() {
for (int i=0; i<getOtherLinks().size(); i++) {
Link link = (Link)getOtherLinks().get(i);
if (link.getRel() != null && link.getRel().equals("edit")) {
return link.getHrefResolved();
}
}
return null;
}
void addToCollection(ClientCollection col) throws ProponoException {
setCollection(col);
EntityEnclosingMethod method = new PostMethod(getCollection().getHrefResolved());
addAuthentication(method);
StringWriter sw = new StringWriter();
int code = -1;
try {
Atom10Generator.serializeEntry(this, sw);
method.setRequestEntity(new StringRequestEntity(sw.toString()));
method.setRequestHeader(
"Content-type", "application/atom+xml; charset=utf-8");
getHttpClient().executeMethod(method);
InputStream is = method.getResponseBodyAsStream();
code = method.getStatusCode();
if (code != 200 && code != 201) {
throw new ProponoException(
"ERROR HTTP status=" + code + " : " + Utilities.streamToString(is));
}
Entry romeEntry = Atom10Parser.parseEntry(
new InputStreamReader(is), getCollection().getHrefResolved());
BeanUtils.copyProperties(this, romeEntry);
} catch (Exception e) {
String msg = "ERROR: saving entry, HTTP code: " + code;
logger.debug(msg, e);
throw new ProponoException(msg, e);
} finally {
method.releaseConnection();
}
Header locationHeader = method.getResponseHeader("Location");
if (locationHeader == null) {
logger.warn("WARNING added entry, but no location header returned");
} else if (getEditURI() == null) {
List links = getOtherLinks();
Link link = new Link();
link.setHref(locationHeader.getValue());
link.setRel("edit");
links.add(link);
setOtherLinks(links);
}
}
void addAuthentication(HttpMethodBase method) throws ProponoException {
if (service != null) {
service.addAuthentication(method);
} else if (collection != null) {
collection.addAuthentication(method);
}
}
HttpClient getHttpClient() {
if (service != null) {
return service.getHttpClient();
} else if (collection != null) {
return collection.getHttpClient();
}
return null;
}
}

View file

@ -1,322 +0,0 @@
/*
* 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.client;
import com.sun.syndication.feed.atom.Content;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.impl.Atom10Generator;
import com.sun.syndication.io.impl.Atom10Parser;
import com.sun.syndication.propono.utils.ProponoException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import com.sun.syndication.propono.utils.Utilities;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.JDOMException;
/**
* Client implementation of Atom media-link entry, an Atom entry that provides
* meta-data for a media file (e.g. uploaded image or audio file).
*/
public class ClientMediaEntry extends ClientEntry {
private static final Log logger = LogFactory.getLog(ClientMediaEntry.class);
private String slug = null;
private byte[] bytes;
private InputStream inputStream;
/**
* Create ClientMedieEntry for service and collection.
*/
public ClientMediaEntry(ClientAtomService service, ClientCollection collection) {
super(service, collection);
}
public ClientMediaEntry(ClientAtomService service, ClientCollection collection,
Entry entry, boolean partial) throws ProponoException {
super(service, collection, entry, partial);
}
public ClientMediaEntry(ClientAtomService service, ClientCollection collection,
String title, String slug, String contentType, InputStream is) {
this(service, collection);
this.inputStream = is;
setTitle(title);
setSlug(slug);
Content content = new Content();
content.setType(contentType);
List contents = new ArrayList();
contents.add(content);
setContents(contents);
}
public ClientMediaEntry(ClientAtomService service, ClientCollection collection,
String title, String slug, String contentType, byte[] bytes) {
this(service, collection);
this.bytes = bytes;
setTitle(title);
setSlug(slug);
Content content = new Content();
content.setType(contentType);
List contents = new ArrayList();
contents.add(content);
setContents(contents);
}
/**
* Get bytes of media resource associated with entry.
* @return Bytes or null if none available or if entry uses an InputStream instead.
*/
public byte[] getBytes() {
return bytes;
}
/**
* Set media resource data as a byte array, don't try this if you have already
* set the data as an InputStream.
*/
public void setBytes(byte[] bytes) {
if (inputStream != null) {
throw new IllegalStateException("ERROR: already has inputStream, cannot set both inputStream and bytes");
}
this.bytes = bytes;
}
/**
* Get input stream for media resource associated with this entry.
* @return InputStream or null if none available or if entry uses bytes instead.
*/
public InputStream getInputStream() {
return inputStream;
}
/**
* Set media resource data as an input stream, don't try this if you have already
* set the data as a byte array.
*/
public void setInputStream(InputStream inputStream) {
if (bytes != null) {
throw new IllegalStateException("ERROR: already has bytes, cannot set both bytes and inputStream");
}
this.inputStream = inputStream;
}
/**
* Get media link URI for editing the media resource associated with this
* entry via HTTP PUT or DELETE.
*/
public String getMediaLinkURI() {
for (int i=0; i<getOtherLinks().size(); i++) {
Link link = (Link)getOtherLinks().get(i);
if (link.getRel() != null && link.getRel().equals("edit-media")) {
return link.getHrefResolved();
}
}
return null;
}
/**
* Get media resource as an InputStream, should work regardless of whether
* you set the media resource data as an InputStream or as a byte array.
*/
public InputStream getAsStream() throws ProponoException {
if (getContents() != null && getContents().size() > 0) {
Content c = (Content)getContents().get(0);
if (c.getSrc() != null) {
return getResourceAsStream();
} else if (inputStream != null) {
return inputStream;
} else if (bytes != null) {
return new ByteArrayInputStream(bytes);
} else {
throw new ProponoException("ERROR: no src URI or binary data to return");
}
}
else {
throw new ProponoException("ERROR: no content found in entry");
}
}
private InputStream getResourceAsStream() throws ProponoException {
if (getEditURI() == null) {
throw new ProponoException("ERROR: not yet saved to server");
}
GetMethod method = new GetMethod(((Content)getContents()).getSrc());
try {
getCollection().getHttpClient().executeMethod(method);
if (method.getStatusCode() != 200) {
throw new ProponoException("ERROR HTTP status=" + method.getStatusCode());
}
return method.getResponseBodyAsStream();
} catch (IOException e) {
throw new ProponoException("ERROR: getting media entry", e);
}
}
/**
* Update entry on server.
*/
public void update() throws ProponoException {
if (partial) throw new ProponoException("ERROR: attempt to update partial entry");
EntityEnclosingMethod method = null;
Content updateContent = (Content)getContents().get(0);
try {
if (getMediaLinkURI() != null && getBytes() != null) {
// existing media entry and new file, so PUT file to edit-media URI
method = new PutMethod(getMediaLinkURI());
if (inputStream != null) {
method.setRequestEntity(new InputStreamRequestEntity(inputStream));
} else {
method.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(getBytes())));
}
method.setRequestHeader("Content-type", updateContent.getType());
}
else if (getEditURI() != null) {
// existing media entry and NO new file, so PUT entry to edit URI
method = new PutMethod(getEditURI());
StringWriter sw = new StringWriter();
Atom10Generator.serializeEntry(this, sw);
method.setRequestEntity(new StringRequestEntity(sw.toString()));
method.setRequestHeader(
"Content-type", "application/atom+xml; charset=utf8");
} else {
throw new ProponoException("ERROR: media entry has no edit URI or media-link URI");
}
this.getCollection().addAuthentication(method);
method.addRequestHeader("Title", getTitle());
getCollection().getHttpClient().executeMethod(method);
if (inputStream != null) inputStream.close();
InputStream is = method.getResponseBodyAsStream();
if (method.getStatusCode() != 200 && method.getStatusCode() != 201) {
throw new ProponoException(
"ERROR HTTP status=" + method.getStatusCode() + " : " + Utilities.streamToString(is));
}
} catch (Exception e) {
throw new ProponoException("ERROR: saving media entry");
}
if (method.getStatusCode() != 201) {
throw new ProponoException("ERROR HTTP status=" + method.getStatusCode());
}
}
/** Package access, to be called by DefaultClientCollection */
void addToCollection(ClientCollection col) throws ProponoException {
setCollection(col);
EntityEnclosingMethod method = new PostMethod(col.getHrefResolved());
getCollection().addAuthentication(method);
StringWriter sw = new StringWriter();
boolean error = false;
try {
Content c = (Content)getContents().get(0);
if (inputStream != null) {
method.setRequestEntity(new InputStreamRequestEntity(inputStream));
} else {
method.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(getBytes())));
}
method.setRequestHeader("Content-type", c.getType());
method.setRequestHeader("Title", getTitle());
method.setRequestHeader("Slug", getSlug());
getCollection().getHttpClient().executeMethod(method);
if (inputStream != null) inputStream.close();
InputStream is = method.getResponseBodyAsStream();
if (method.getStatusCode() == 200 || method.getStatusCode() == 201) {
Entry romeEntry = Atom10Parser.parseEntry(
new InputStreamReader(is), col.getHrefResolved());
BeanUtils.copyProperties(this, romeEntry);
} else {
throw new ProponoException(
"ERROR HTTP status-code=" + method.getStatusCode()
+ " status-line: " + method.getStatusLine());
}
} catch (IOException ie) {
throw new ProponoException("ERROR: saving media entry", ie);
} catch (JDOMException je) {
throw new ProponoException("ERROR: saving media entry", je);
} catch (FeedException fe) {
throw new ProponoException("ERROR: saving media entry", fe);
} catch (IllegalAccessException ae) {
throw new ProponoException("ERROR: saving media entry", ae);
} catch (InvocationTargetException te) {
throw new ProponoException("ERROR: saving media entry", te);
}
Header locationHeader = method.getResponseHeader("Location");
if (locationHeader == null) {
logger.warn("WARNING added entry, but no location header returned");
} else if (getEditURI() == null) {
List links = getOtherLinks();
Link link = new Link();
link.setHref(locationHeader.getValue());
link.setRel("edit");
links.add(link);
setOtherLinks(links);
}
}
/** Set string to be used in file name of new media resource on server. */
public String getSlug() {
return slug;
}
/** Get string to be used in file name of new media resource on server. */
public void setSlug(String slug) {
this.slug = slug;
}
}

View file

@ -1,66 +0,0 @@
/*
* 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.client;
import com.sun.syndication.propono.atom.common.AtomService;
import com.sun.syndication.propono.atom.common.Workspace;
import com.sun.syndication.propono.atom.common.Workspace;
import com.sun.syndication.propono.utils.ProponoException;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
/**
* Represents Atom protocol workspace on client-side.
* It extends the common
* {@link com.sun.syndication.propono.atom.common.Workspace}
* to return
* {@link com.sun.syndication.propono.atom.client.ClientCollection}
* objects instead of common
* {@link com.sun.syndication.propono.atom.common.Collection}s.
*/
public class ClientWorkspace extends Workspace {
private ClientAtomService atomService = null;
ClientWorkspace(Element e, ClientAtomService atomService, String baseURI) throws ProponoException {
super("dummy", "dummy");
this.atomService = atomService;
parseWorkspaceElement(e, baseURI);
}
/**
* Package access to parent service.
*/
ClientAtomService getAtomService() {
return atomService;
}
/** Deserialize a Atom workspace XML element into an object */
protected void parseWorkspaceElement(Element element, String baseURI) throws ProponoException {
Element titleElem = element.getChild("title", AtomService.ATOM_FORMAT);
setTitle(titleElem.getText());
if (titleElem.getAttribute("type", AtomService.ATOM_FORMAT) != null) {
setTitleType(titleElem.getAttribute("type", AtomService.ATOM_FORMAT).getValue());
}
List collections = element.getChildren("collection", AtomService.ATOM_PROTOCOL);
Iterator iter = collections.iterator();
while (iter.hasNext()) {
Element e = (Element) iter.next();
addCollection(new ClientCollection(e, this, baseURI));
}
}
}

View file

@ -1,124 +0,0 @@
/*
* 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.client;
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.WireFeedInput;
import com.sun.syndication.propono.utils.ProponoException;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;
/**
* Enables iteration over entries in Atom protocol collection.
*/
public class EntryIterator implements Iterator {
static final Log logger = LogFactory.getLog(EntryIterator.class);
private final ClientCollection collection;
int maxEntries = 20;
int offset = 0;
Iterator members = null;
Feed col = null;
String collectionURI;
String nextURI;
EntryIterator(ClientCollection collection) throws ProponoException {
this.collection = collection;
collectionURI = collection.getHrefResolved();
nextURI = collectionURI;
getNextEntries();
}
/**
* Returns true if more entries are available.
*/
public boolean hasNext() {
if (!members.hasNext()) {
try {
getNextEntries();
} catch (Exception ignored) {
logger.error("ERROR getting next entries", ignored);
}
}
return members.hasNext();
}
/**
* Get next entry in collection.
*/
public Object next() {
if (hasNext()) {
Entry romeEntry = (Entry)members.next();
try {
if (!romeEntry.isMediaEntry()) {
return new ClientEntry(null, collection, romeEntry, true);
} else {
return new ClientMediaEntry(null, collection, romeEntry, true);
}
} catch (ProponoException e) {
throw new RuntimeException("Unexpected exception creating ClientEntry or ClientMedia", e);
}
}
throw new NoSuchElementException();
}
/**
* Remove entry is not implemented.
*/
public void remove() {
// optional method, not implemented
}
private void getNextEntries() throws ProponoException {
if (nextURI == null) return;
GetMethod colGet = new GetMethod( collection.getHrefResolved(nextURI) );
collection.addAuthentication(colGet);
try {
collection.getHttpClient().executeMethod(colGet);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(colGet.getResponseBodyAsStream());
WireFeedInput feedInput = new WireFeedInput();
col = (Feed) feedInput.build(doc);
} catch (Exception e) {
throw new ProponoException("ERROR: fetching or parsing next entries, HTTP code: " + (colGet != null ? colGet.getStatusCode() : -1), e);
} finally {
colGet.releaseConnection();
}
members = col.getEntries().iterator();
offset += col.getEntries().size();
nextURI = null;
List altLinks = col.getOtherLinks();
if (altLinks != null) {
Iterator iter = altLinks.iterator();
while (iter.hasNext()) {
Link link = (Link)iter.next();
if ("next".equals(link.getRel())) {
nextURI = link.getHref();
}
}
}
}
}

View file

@ -1,67 +0,0 @@
/*
* Copyright 2009 Dave Johnson (Blogapps project)
*
* 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.client;
import com.sun.syndication.propono.utils.ProponoException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
public class GDataAuthStrategy implements AuthStrategy {
private String email;
private String password;
private String service;
private String authToken;
public GDataAuthStrategy(String email, String password, String service) throws ProponoException {
this.email = email;
this.password = password;
this.service = service;
init();
}
private void init() throws ProponoException {
try {
HttpClient httpClient = new HttpClient();
PostMethod method = new PostMethod("https://www.google.com/accounts/ClientLogin");
NameValuePair[] data = {
new NameValuePair("Email", email),
new NameValuePair("Passwd", password),
new NameValuePair("accountType", "GOOGLE"),
new NameValuePair("service", service),
new NameValuePair("source", "ROME Propono Atompub Client")
};
method.setRequestBody(data);
httpClient.executeMethod(method);
String responseBody = method.getResponseBodyAsString();
int authIndex = responseBody.indexOf("Auth=");
authToken = "GoogleLogin auth=" + responseBody.trim().substring(authIndex + 5);
} catch (Throwable t) {
t.printStackTrace();
throw new ProponoException("ERROR obtaining Google authentication string", t);
}
}
public void addAuthentication(HttpClient httpClient, HttpMethodBase method) throws ProponoException {
httpClient.getParams().setAuthenticationPreemptive(true);
method.setRequestHeader("Authorization", authToken);
}
}

View file

@ -1,31 +0,0 @@
/*
* Copyright 2009 Dave Johnson (Blogapps project)
*
* 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.client;
import com.sun.syndication.propono.utils.ProponoException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
/**
* No authentication
*/
public class NoAuthStrategy implements AuthStrategy {
public void addAuthentication(HttpClient httpClient, HttpMethodBase method) throws ProponoException {
// no-op
}
}

View file

@ -1,302 +0,0 @@
/*
* Copyright 2009 Dave Johnson (Blogapps project)
*
* 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.client;
import com.sun.syndication.propono.utils.ProponoException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.util.ParameterParser;
/**
* Strategy for using OAuth.
*/
public class OAuthStrategy implements AuthStrategy {
private State state = State.UNAUTHORIZED;
private enum State {
UNAUTHORIZED, // have not sent any requests
REQUEST_TOKEN, // have a request token
AUTHORIZED, // are authorized
ACCESS_TOKEN // have access token, ready to make calls
}
private String username;
private String consumerKey;
private String consumerSecret;
private String keyType;
private String reqUrl;
private String authzUrl;
private String accessUrl;
private String nonce;
private long timestamp;
private String requestToken = null;
private String accessToken = null;
private String tokenSecret = null;
/**
* Create OAuth authentcation strategy and negotiate with services to
* obtain access token to be used in subsequent calls.
*
* @param username Username to be used in authentication
* @param key Consumer key
* @param secret Consumer secret
* @param keyType Key type (e.g. "HMAC-SHA1")
* @param reqUrl URL of request token service
* @param authzUrl URL of authorize service
* @param accessUrl URL of acess token service
* @throws ProponoException on any sort of initialization error
*/
public OAuthStrategy(
String username, String key, String secret, String keyType,
String reqUrl, String authzUrl, String accessUrl) throws ProponoException {
this.username = username;
this.reqUrl = reqUrl;
this.authzUrl = authzUrl;
this.accessUrl = accessUrl;
this.consumerKey = key;
this.consumerSecret = secret;
this.keyType = keyType;
this.nonce = UUID.randomUUID().toString();
this.timestamp = (long)(new Date().getTime()/1000L);
init();
}
private void init() throws ProponoException {
callOAuthUri(reqUrl);
callOAuthUri(authzUrl);
callOAuthUri(accessUrl);
}
public void addAuthentication(HttpClient httpClient, HttpMethodBase method) throws ProponoException {
if (state != State.ACCESS_TOKEN) {
throw new ProponoException("ERROR: authentication strategy failed init");
}
// add OAuth name/values to request query string
// wish we didn't have to parse them apart first, ugh
List originalqlist = null;
if (method.getQueryString() != null) {
String qstring = method.getQueryString().trim();
qstring = qstring.startsWith("?") ? qstring.substring(1) : qstring;
originalqlist = new ParameterParser().parse(qstring, '&');
} else {
originalqlist = new ArrayList();
}
// put query string into hashmap form to please OAuth.net classes
Map params = new HashMap();
for (Iterator it = originalqlist.iterator(); it.hasNext();) {
NameValuePair pair = (NameValuePair)it.next();
params.put(pair.getName(), pair.getValue());
}
// add OAuth params to query string
params.put("xoauth_requestor_id", username);
params.put("oauth_consumer_key", consumerKey);
params.put("oauth_signature_method", keyType);
params.put("oauth_timestamp", Long.toString(timestamp));
params.put("oauth_nonce", nonce);
params.put("oauth_token", accessToken);
params.put("oauth_token_secret", tokenSecret);
// sign complete URI
String finalUri = null;
OAuthServiceProvider provider =
new OAuthServiceProvider(reqUrl, authzUrl, accessUrl);
OAuthConsumer consumer =
new OAuthConsumer(null, consumerKey, consumerSecret, provider);
OAuthAccessor accessor = new OAuthAccessor(consumer);
accessor.tokenSecret = tokenSecret;
OAuthMessage message;
try {
message = new OAuthMessage(
method.getName(), method.getURI().toString(), params.entrySet());
message.sign(accessor);
finalUri = OAuth.addParameters(message.URL, message.getParameters());
} catch (Exception ex) {
throw new ProponoException("ERROR: OAuth signing request", ex);
}
// pull query string off and put it back onto method
method.setQueryString(finalUri.substring(finalUri.lastIndexOf("?")));
}
private void callOAuthUri(String uri) throws ProponoException {
final HttpClient httpClient = new HttpClient();
final HttpMethodBase method;
final String content;
Map<String, String> params = new HashMap<String, String>();
if (params == null) {
params = new HashMap<String, String>();
}
params.put("oauth_version", "1.0");
if (username != null) {
params.put("xoauth_requestor_id", username);
}
params.put("oauth_consumer_key", consumerKey);
params.put("oauth_signature_method", keyType);
params.put("oauth_timestamp", Long.toString(timestamp));
params.put("oauth_nonce", nonce);
params.put("oauth_callback", "none");
OAuthServiceProvider provider =
new OAuthServiceProvider(reqUrl, authzUrl, accessUrl);
OAuthConsumer consumer =
new OAuthConsumer(null, consumerKey, consumerSecret, provider);
OAuthAccessor accessor = new OAuthAccessor(consumer);
if (state == State.UNAUTHORIZED) {
try {
OAuthMessage message = new OAuthMessage("GET", uri, params.entrySet());
message.sign(accessor);
String finalUri = OAuth.addParameters(message.URL, message.getParameters());
method = new GetMethod(finalUri);
httpClient.executeMethod(method);
content = method.getResponseBodyAsString();
} catch (Exception e) {
throw new ProponoException("ERROR fetching request token", e);
}
} else if (state == State.REQUEST_TOKEN) {
try {
params.put("oauth_token", requestToken);
params.put("oauth_token_secret", tokenSecret);
accessor.tokenSecret = tokenSecret;
OAuthMessage message = new OAuthMessage("POST", uri, params.entrySet());
message.sign(accessor);
String finalUri = OAuth.addParameters(message.URL, message.getParameters());
method = new PostMethod(finalUri);
httpClient.executeMethod(method);
content = method.getResponseBodyAsString();
} catch (Exception e) {
throw new ProponoException("ERROR fetching request token", e);
}
} else if (state == State.AUTHORIZED) {
try {
params.put("oauth_token", accessToken);
params.put("oauth_token_secret", tokenSecret);
accessor.tokenSecret = tokenSecret;
OAuthMessage message = new OAuthMessage("GET", uri, params.entrySet());
message.sign(accessor);
String finalUri = OAuth.addParameters(message.URL, message.getParameters());
method = new GetMethod(finalUri);
httpClient.executeMethod(method);
content = method.getResponseBodyAsString();
} catch (Exception e) {
throw new ProponoException("ERROR fetching request token", e);
}
} else {
method = null;
content = null;
return;
}
String token = null;
String secret = null;
if (content != null) {
String[] settings = content.split("&");
for (int i=0; i<settings.length; i++) {
String[] setting = settings[i].split("=");
if (setting.length > 1) {
if ("oauth_token".equals(setting[0])) {
token = setting[1];
} else if ("oauth_token_secret".equals(setting[0])) {
secret = setting[1];
}
}
}
}
switch (state) {
case UNAUTHORIZED:
if (token != null && secret != null) {
requestToken = token;
tokenSecret = secret;
state = State.REQUEST_TOKEN;
} else {
throw new ProponoException("ERROR: requestToken or tokenSecret is null");
}
break;
case REQUEST_TOKEN:
if (method.getStatusCode() == 200) {
state = State.AUTHORIZED;
} else {
throw new ProponoException("ERROR: authorization returned code: " + method.getStatusCode());
}
break;
case AUTHORIZED:
if (token != null && secret != null) {
accessToken = token;
tokenSecret = secret;
state = State.ACCESS_TOKEN;
} else {
throw new ProponoException("ERROR: accessToken or tokenSecret is null");
}
break;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -1,122 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common;
import com.sun.syndication.propono.utils.ProponoException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
/**
* Models an Atom Publishing Protocol Service Document.
* Is able to read a Service document from a JDOM Document
* and to write Service document out as a JDOM Document.
*/
public class AtomService {
private List workspaces = new ArrayList();
/** Namespace for Atom Syndication Format */
public static Namespace ATOM_FORMAT =
Namespace.getNamespace("atom","http://www.w3.org/2005/Atom");
/** Namespace for Atom Publishing Protocol */
public static Namespace ATOM_PROTOCOL =
Namespace.getNamespace("app","http://www.w3.org/2007/app");
/**
* Create new and empty Atom service
*/
public AtomService() {
}
/**
* Add Workspace to service.
*/
public void addWorkspace(Workspace workspace) {
workspaces.add(workspace);
}
/**
* Get Workspaces available from service.
*/
public List getWorkspaces() {
return workspaces;
}
/**
* Set Workspaces of service.
*/
public void setWorkspaces(List workspaces) {
this.workspaces = workspaces;
}
/**
* Find workspace by title.
* @param title Match this title
* @return Matching Workspace or null if none found.
*/
public Workspace findWorkspace(String title) {
for (Iterator it = workspaces.iterator(); it.hasNext();) {
Workspace ws = (Workspace) it.next();
if (title.equals(ws.getTitle())) {
return ws;
}
}
return null;
}
/**
* Deserialize an Atom service XML document into an object
*/
public static AtomService documentToService(Document document) throws ProponoException {
AtomService service = new AtomService();
Element root = document.getRootElement();
List spaces = root.getChildren("workspace", ATOM_PROTOCOL);
Iterator iter = spaces.iterator();
while (iter.hasNext()) {
Element e = (Element) iter.next();
service.addWorkspace(Workspace.elementToWorkspace(e));
}
return service;
}
/**
* Serialize an AtomService object into an XML document
*/
public Document serviceToDocument() {
AtomService service = this;
Document doc = new Document();
Element root = new Element("service", ATOM_PROTOCOL);
doc.setRootElement(root);
Iterator iter = service.getWorkspaces().iterator();
while (iter.hasNext()) {
Workspace space = (Workspace) iter.next();
root.addContent(space.workspaceToElement());
}
return doc;
}
}

View file

@ -1,155 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common;
import com.sun.syndication.feed.atom.Category;
import com.sun.syndication.io.impl.Atom10Parser;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
/**
* Models an Atom protocol Categories element, which may contain ROME Atom
* {@link com.sun.syndication.feed.atom.Category} elements.
*/
public class Categories {
private List categories = new ArrayList(); // of Category objects
private String baseURI = null;
private Element categoriesElement = null;
private String href = null;
private String scheme = null;
private boolean fixed = false;
public Categories() {
}
/** Load select from XML element */
public Categories(Element e, String baseURI) {
this.categoriesElement = e;
this.baseURI = baseURI;
parseCategoriesElement(e);
}
/** Add category list of those specified */
public void addCategory(Category cat) {
categories.add(cat);
}
/**
* Iterate over Category objects
* @return List of ROME Atom {@link com.sun.syndication.feed.atom.Category}
*/
public List getCategories() {
return categories;
}
/** True if clients MUST use one of the categories specified */
public boolean isFixed() {
return fixed;
}
/** True if clients MUST use one of the categories specified */
public void setFixed(boolean fixed) {
this.fixed = fixed;
}
/** Category URI scheme to use for Categories without a scheme */
public String getScheme() {
return scheme;
}
/** Category URI scheme to use for Categories without a scheme */
public void setScheme(String scheme) {
this.scheme = scheme;
}
/** URI of out-of-line categories */
public String getHref() {
return href;
}
/** URI of out-of-line categories */
public void setHref(String href) {
this.href = href;
}
/** Get unresolved URI of the collection, or null if impossible to determine */
public String getHrefResolved() {
if (Atom10Parser.isAbsoluteURI(href)) {
return href;
} else if (baseURI != null && categoriesElement != null) {
return Atom10Parser.resolveURI(
baseURI, categoriesElement, href);
}
return null;
}
public Element categoriesToElement() {
Categories cats = this;
Element catsElem = new Element("categories", AtomService.ATOM_PROTOCOL);
catsElem.setAttribute("fixed", cats.isFixed() ? "yes" : "no", AtomService.ATOM_PROTOCOL);
if (cats.getScheme() != null) {
catsElem.setAttribute("scheme", cats.getScheme(), AtomService.ATOM_PROTOCOL);
}
if (cats.getHref() != null) {
catsElem.setAttribute("href", cats.getHref(), AtomService.ATOM_PROTOCOL);
} else {
// Loop to create <atom:category> elements
for (Iterator catIter = cats.getCategories().iterator(); catIter.hasNext();) {
Category cat = (Category) catIter.next();
Element catElem = new Element("category", AtomService.ATOM_FORMAT);
catElem.setAttribute("term", cat.getTerm(), AtomService.ATOM_FORMAT);
if (cat.getScheme() != null) { // optional
catElem.setAttribute("scheme", cat.getScheme(), AtomService.ATOM_FORMAT);
}
if (cat.getLabel() != null) { // optional
catElem.setAttribute("label", cat.getLabel(), AtomService.ATOM_FORMAT);
}
catsElem.addContent(catElem);
}
}
return catsElem;
}
protected void parseCategoriesElement(Element catsElem) {
if (catsElem.getAttribute("href", AtomService.ATOM_PROTOCOL) != null) {
setHref(catsElem.getAttribute("href", AtomService.ATOM_PROTOCOL).getValue());
}
if (catsElem.getAttribute("fixed", AtomService.ATOM_PROTOCOL) != null) {
if ("yes".equals(catsElem.getAttribute("fixed", AtomService.ATOM_PROTOCOL).getValue())) {
setFixed(true);
}
}
if (catsElem.getAttribute("scheme", AtomService.ATOM_PROTOCOL) != null) {
setScheme(catsElem.getAttribute("scheme", AtomService.ATOM_PROTOCOL).getValue());
}
// Loop to parse <atom:category> elemenents to Category objects
List catElems = catsElem.getChildren("category", AtomService.ATOM_FORMAT);
for (Iterator catIter = catElems.iterator(); catIter.hasNext();) {
Element catElem = (Element) catIter.next();
Category cat = new Category();
cat.setTerm(catElem.getAttributeValue("term", AtomService.ATOM_FORMAT));
cat.setLabel(catElem.getAttributeValue("label", AtomService.ATOM_FORMAT));
cat.setScheme(catElem.getAttributeValue("scheme", AtomService.ATOM_FORMAT));
addCategory(cat);
}
}
}

View file

@ -1,252 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common;
import com.sun.syndication.io.impl.Atom10Parser;
import com.sun.syndication.propono.utils.ProponoException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
/**
* Models an Atom workspace collection.
*/
public class Collection {
public static final String ENTRY_TYPE = "application/atom+xml;type=entry";
private Element collectionElement = null;
private String baseURI = null;
private String title = null;
private String titleType = null; // may be TEXT, HTML, XHTML
private List accepts = new ArrayList(); // of Strings
private String listTemplate = null;
private String href = null;
private List categories = new ArrayList(); // of Categories objects
/**
* Collection MUST have title and href.
* @param title Title for collection
* @param titleType Content type of title (null for plain text)
* @param href Collection URI.
*/
public Collection(String title, String titleType, String href) {
this.title = title;
this.titleType = titleType;
this.href = href;
}
/** Load self from XML element */
public Collection(Element e) throws ProponoException {
this.collectionElement = e;
this.parseCollectionElement(e);
}
/** Load self from XML element and base URI for resolving relative URIs */
public Collection(Element e, String baseURI) throws ProponoException {
this.collectionElement = e;
this.baseURI = baseURI;
this.parseCollectionElement(e);
}
/**
* List of content-type ranges accepted by collection.
*/
public List getAccepts() {
return accepts;
}
public void addAccept(String accept) {
this.accepts.add(accept);
}
public void setAccepts(List accepts) {
this.accepts = accepts;
}
/** The URI of the collection */
public String getHref() {
return href;
}
/**
* Set URI of collection
*/
public void setHref(String href) {
this.href = href;
}
/** Get resolved URI of the collection, or null if impossible to determine */
public String getHrefResolved() {
if (Atom10Parser.isAbsoluteURI(href)) {
return href;
} else if (baseURI != null && collectionElement != null) {
int lastslash = baseURI.lastIndexOf("/");
return Atom10Parser.resolveURI(baseURI.substring(0, lastslash), collectionElement, href);
}
return null;
}
/** Get resolved URI using collection's baseURI, or null if impossible to determine */
public String getHrefResolved(String relativeUri) {
if (Atom10Parser.isAbsoluteURI(relativeUri)) {
return relativeUri;
} else if (baseURI != null && collectionElement != null) {
int lastslash = baseURI.lastIndexOf("/");
return Atom10Parser.resolveURI(baseURI.substring(0, lastslash), collectionElement, relativeUri);
}
return null;
}
/** Must have human readable title */
public String getTitle() {
return title;
}
/**
* Set title of collection.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Type of title ("text", "html" or "xhtml")
*/
public String getTitleType() {
return titleType;
}
/**
* Type of title ("text", "html" or "xhtml")
*/
public void setTitleType(String titleType) {
this.titleType = titleType;
}
/** Workspace can have multiple Categories objects */
public void addCategories(Categories cats) {
categories.add(cats);
}
/**
* Get categories allowed by collection.
* @return Collection of {@link com.sun.syndication.propono.atom.common.Categories} objects.
*/
public List getCategories() {
return categories;
}
/**
* Returns true if contentType is accepted by collection.
*/
public boolean accepts(String ct) {
for (Iterator it = accepts.iterator(); it.hasNext();) {
String accept = (String)it.next();
if (accept != null && accept.trim().equals("*/*")) return true;
String entryType = "application/atom+xml";
boolean entry = entryType.equals(ct);
if (entry && null == accept) {
return true;
} else if (entry && "entry".equals(accept)) {
return true;
} else if (entry && entryType.equals(accept)) {
return true;
} else {
String[] rules = (String[])accepts.toArray(new String[accepts.size()]);
for (int i=0; i<rules.length; i++) {
String rule = rules[i].trim();
if (rule.equals(ct)) return true;
int slashstar = rule.indexOf("/*");
if (slashstar > 0) {
rule = rule.substring(0, slashstar + 1);
if (ct.startsWith(rule)) return true;
}
}
}
}
return false;
}
/**
* Serialize an AtomService.Collection into an XML element
*/
public Element collectionToElement() {
Collection collection = this;
Element element = new Element("collection", AtomService.ATOM_PROTOCOL);
element.setAttribute("href", collection.getHref());
Element titleElem = new Element("title", AtomService.ATOM_FORMAT);
titleElem.setText(collection.getTitle());
if (collection.getTitleType() != null && !collection.getTitleType().equals("TEXT")) {
titleElem.setAttribute("type", collection.getTitleType(), AtomService.ATOM_FORMAT);
}
element.addContent(titleElem);
// Loop to create <app:categories> elements
for (Iterator it = collection.getCategories().iterator(); it.hasNext();) {
Categories cats = (Categories)it.next();
element.addContent(cats.categoriesToElement());
}
for (Iterator it = collection.getAccepts().iterator(); it.hasNext();) {
String range = (String)it.next();
Element acceptElem = new Element("accept", AtomService.ATOM_PROTOCOL);
acceptElem.setText(range);
element.addContent(acceptElem);
}
return element;
}
/** Deserialize an Atom service collection XML element into an object */
public Collection elementToCollection(Element element) throws ProponoException {
return new Collection(element);
}
protected void parseCollectionElement(Element element) throws ProponoException {
setHref(element.getAttribute("href").getValue());
Element titleElem = element.getChild("title", AtomService.ATOM_FORMAT);
if (titleElem != null) {
setTitle(titleElem.getText());
if (titleElem.getAttribute("type", AtomService.ATOM_FORMAT) != null) {
setTitleType(titleElem.getAttribute("type", AtomService.ATOM_FORMAT).getValue());
}
}
List acceptElems = element.getChildren("accept", AtomService.ATOM_PROTOCOL);
if (acceptElems != null && acceptElems.size() > 0) {
for (Iterator it = acceptElems.iterator(); it.hasNext();) {
Element acceptElem = (Element)it.next();
addAccept(acceptElem.getTextTrim());
}
}
// Loop to parse <app:categories> element to Categories objects
List catsElems = element.getChildren("categories", AtomService.ATOM_PROTOCOL);
for (Iterator catsIter = catsElems.iterator(); catsIter.hasNext();) {
Element catsElem = (Element) catsIter.next();
Categories cats = new Categories(catsElem, baseURI);
addCategories(cats);
}
}
}

View file

@ -1,147 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common;
import com.sun.syndication.propono.utils.ProponoException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
/**
* Models an Atom workspace.
*/
public class Workspace {
private String title = null;
private String titleType = null; // may be TEXT, HTML, XHTML
private List collections = new ArrayList();
/**
* Collection MUST have title.
* @param title Title for collection
* @param titleType Content type of title (null for plain text)
*/
public Workspace(String title, String titleType) {
this.title = title;
this.titleType = titleType;
}
public Workspace(Element elem) throws ProponoException {
parseWorkspaceElement(elem);
}
/** Iterate over collections in workspace */
public List getCollections() {
return collections;
}
/** Add new collection to workspace */
public void addCollection(Collection col) {
collections.add(col);
}
/**
* DefaultWorkspace must have a human readable title
*/
public String getTitle() {
return title;
}
/**
* Set title of workspace.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Get title type ("text", "html", "xhtml" or MIME content-type)
*/
public String getTitleType() {
return titleType;
}
/**
* Set title type ("text", "html", "xhtml" or MIME content-type)
*/
public void setTitleType(String titleType) {
this.titleType = titleType;
}
/**
* Find collection by title and/or content-type.
* @param title Title or null to match all titles.
* @param contentType Content-type or null to match all content-types.
* @return First Collection that matches title and/or content-type.
*/
public Collection findCollection(String title, String contentType) {
for (Iterator it = collections.iterator(); it.hasNext();) {
Collection col = (Collection) it.next();
if (title != null && col.accepts(contentType)) {
return col;
} else if (col.accepts(contentType)) {
return col;
}
}
return null;
}
/** Deserialize a Atom workspace XML element into an object */
public static Workspace elementToWorkspace(Element element) throws ProponoException {
return new Workspace(element);
}
/**
* Serialize an AtomService.DefaultWorkspace object into an XML element
*/
public Element workspaceToElement() {
Workspace space = this;
Element element = new Element("workspace", AtomService.ATOM_PROTOCOL);
Element titleElem = new Element("title", AtomService.ATOM_FORMAT);
titleElem.setText(space.getTitle());
if (space.getTitleType() != null && !space.getTitleType().equals("TEXT")) {
titleElem.setAttribute("type", space.getTitleType(), AtomService.ATOM_FORMAT);
}
element.addContent(titleElem);
Iterator iter = space.getCollections().iterator();
while (iter.hasNext()) {
Collection col = (Collection) iter.next();
element.addContent(col.collectionToElement());
}
return element;
}
/** Deserialize a Atom workspace XML element into an object */
protected void parseWorkspaceElement(Element element) throws ProponoException {
Element titleElem = element.getChild("title", AtomService.ATOM_FORMAT);
setTitle(titleElem.getText());
if (titleElem.getAttribute("type", AtomService.ATOM_FORMAT) != null) {
setTitleType(titleElem.getAttribute("type", AtomService.ATOM_FORMAT).getValue());
}
List collections = element.getChildren("collection", AtomService.ATOM_PROTOCOL);
Iterator iter = collections.iterator();
while (iter.hasNext()) {
Element e = (Element) iter.next();
addCollection(new Collection(e));
}
}
}

View file

@ -1,42 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common.rome;
import com.sun.syndication.feed.module.Module;
import java.util.Date;
/**
* ROME Extension Module to Atom protocol extensions to Atom format.
*/
public interface AppModule extends Module {
public static final String URI = "http://www.w3.org/2007/app";
/** True if entry is a draft */
public Boolean getDraft();
/** Set to true if entry is a draft */
public void setDraft(Boolean draft);
/** Time of last edit */
public Date getEdited();
/** Set time of last edit */
public void setEdited(Date edited);
}

View file

@ -1,85 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common.rome;
import com.sun.syndication.io.impl.DateParser;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.jdom.Element;
import org.jdom.Namespace;
import com.sun.syndication.feed.module.Module;
import com.sun.syndication.io.ModuleGenerator;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
/**
* Creates JDOM representation for APP Extension Module.
*/
public class AppModuleGenerator implements ModuleGenerator {
private static final Namespace APP_NS =
Namespace.getNamespace("app", AppModule.URI);
public String getNamespaceUri() {
return AppModule.URI;
}
private static final Set NAMESPACES;
static {
Set nss = new HashSet();
nss.add(APP_NS);
NAMESPACES = Collections.unmodifiableSet(nss);
}
/** Get namespaces associated with this module */
public Set getNamespaces() {
return NAMESPACES;
}
/** Generate JDOM element for module and add it to parent element */
public void generate(Module module, Element parent) {
AppModule m = (AppModule)module;
if (m.getDraft() != null) {
String draft = m.getDraft().booleanValue() ? "yes" : "no";
Element control = new Element("control", APP_NS);
control.addContent(generateSimpleElement("draft", draft));
parent.addContent(control);
}
if (m.getEdited() != null) {
Element edited = new Element("edited", APP_NS);
// Inclulde millis in date/time
SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
dateFormater.setTimeZone(TimeZone.getTimeZone("GMT"));
edited.addContent(dateFormater.format(m.getEdited()));
parent.addContent(edited);
}
}
private Element generateSimpleElement(String name, String value) {
Element element = new Element(name, APP_NS);
element.addContent(value);
return element;
}
}

View file

@ -1,69 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
* Copyright 2011 The ROME Teams
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common.rome;
import com.sun.syndication.feed.CopyFrom;
import com.sun.syndication.feed.module.ModuleImpl;
import java.util.Date;
/**
* Bean representation of APP module.
*/
public class AppModuleImpl extends ModuleImpl implements AppModule {
private boolean draft = false;
private Date edited = null;
public AppModuleImpl() {
super(AppModule.class, AppModule.URI);
}
/** True if entry is draft */
public Boolean getDraft() {
return draft ? Boolean.TRUE : Boolean.FALSE;
}
/** Set to true if entry is draft */
public void setDraft(Boolean draft) {
this.draft = draft.booleanValue();
}
/** Time of last edit */
public Date getEdited() {
return edited;
}
/** Set time of last edit */
public void setEdited(Date edited) {
this.edited = edited;
}
/** Get interface class of module */
public Class getInterface() {
return AppModule.class;
}
/** Copy from other module */
public void copyFrom(CopyFrom obj) {
AppModule m = (AppModule)obj;
setDraft(m.getDraft());
setEdited(m.getEdited());
}
}

View file

@ -1,66 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.common.rome;
import com.sun.syndication.io.impl.DateParser;
import org.jdom.Element;
import org.jdom.Namespace;
import com.sun.syndication.feed.module.Module;
import com.sun.syndication.io.ModuleParser;
/**
* Parses APP module information from a JDOM element and into
* <code>AppModule</code> form.
*/
public class AppModuleParser implements ModuleParser {
/** Get URI of module namespace */
public String getNamespaceUri() {
return AppModule.URI;
}
/** Get namespace of module */
public Namespace getContentNamespace() {
return Namespace.getNamespace(AppModule.URI);
}
/** Parse JDOM element into module */
public Module parse(Element elem) {
boolean foundSomething = false;
AppModule m = new AppModuleImpl();
Element control = elem.getChild("control", getContentNamespace());
if (control != null) {
Element draftElem = control.getChild("draft", getContentNamespace());
if (draftElem != null) {
if ("yes".equals(draftElem.getText())) m.setDraft(Boolean.TRUE);
if ("no".equals(draftElem.getText())) m.setDraft(Boolean.FALSE);
}
}
Element edited = elem.getChild("edited", getContentNamespace());
if (edited != null) {
try {
m.setEdited(DateParser.parseW3CDateTime(edited.getTextTrim()));
} catch (Exception ignored) {}
}
return m;
}
}

View file

@ -1,53 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.server;
import javax.servlet.http.HttpServletResponse;
/**
* Exception thrown by {@link com.sun.syndication.propono.atom.server.AtomHandler}
* and extended by other Propono Atom exception classes.
*/
public class AtomException extends Exception {
/** Construct new exception */
public AtomException() {
super();
}
/** Construct new exception with message */
public AtomException(String msg) {
super(msg);
}
/** Contruct new exception with message and wrapping existing exception */
public AtomException(String msg, Throwable t) {
super(msg, t);
}
/** Construct new exception to wrap existing one. */
public AtomException(Throwable t) {
super(t);
}
/* Get HTTP status code associated with exception (HTTP 500 server error) */
/**
* Get HTTP status associated with exception.
*/
public int getStatus() {
return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}
}

View file

@ -1,144 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.server;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Feed;
import com.sun.syndication.propono.atom.common.AtomService;
import com.sun.syndication.propono.atom.common.Categories;
/**
* Interface for handling single Atom protocol requests.
*
* <p>To create your own Atom protocol implementation you must implement this
* interface and create a concrete sub-class of
* {@link com.sun.syndication.propono.atom.server.AtomHandlerFactory}
* which is capable of instantiating it.</p>
*/
public interface AtomHandler
{
/**
* Get username of authenticated user. Return the username of the
* authenticated user
*/
public String getAuthenticatedUsername();
/**
* Return
* {@link com.sun.syndication.propono.atom.common.AtomService}
* object that contains the
* {@link com.sun.syndication.propono.atom.common.Workspace} objects
* available to the currently authenticated user and within those the
* {@link com.sun.syndication.propono.atom.common.Collection} avalaible.
*/
public AtomService getAtomService(AtomRequest req) throws AtomException;
/**
* Get categories, a list of Categories objects
*/
public Categories getCategories(AtomRequest req) throws AtomException;
/**
* Return collection or portion of collection specified by request.
* @param req Details of HTTP request
*/
public Feed getCollection(AtomRequest req) throws AtomException;
/**
* Store new entry in collection specified by request and return
* representation of entry as it is stored on server.
* @param req Details of HTTP request
* @return Location URL of new entry
*/
public Entry postEntry(AtomRequest req, Entry entry) throws AtomException;
/**
* Get entry specified by request.
* @param req Details of HTTP request
*/
public Entry getEntry(AtomRequest req) throws AtomException;
/**
* Get media resource specified by request.
* @param req Details of HTTP request
*/
public AtomMediaResource getMediaResource(AtomRequest req) throws AtomException;
/**
* Update entry specified by request and return new entry as represented
* on the server.
* @param req Details of HTTP request
*/
public void putEntry(AtomRequest req, Entry entry) throws AtomException;
/**
* Delete entry specified by request.
* @param req Details of HTTP request
*/
public void deleteEntry(AtomRequest req) throws AtomException;
/**
* Store media data in collection specified by request, create an Atom
* media-link entry to store metadata for the new media file and return
* that entry to the caller.
* @param req Details of HTTP request
* @param entry New entry initialzied with only title and content type
* @return Location URL of new media entry
*/
public Entry postMedia(AtomRequest req, Entry entry) throws AtomException;
/**
* Update the media file part of a media-link entry.
* @param req Details of HTTP request
*/
public void putMedia(AtomRequest req) throws AtomException;
/**
* Return true if specified request represents URI of a Service Document.
* @param req Details of HTTP request
*/
public boolean isAtomServiceURI(AtomRequest req);
/**
* Return true if specified request represents URI of a Categories Document.
* @param req Details of HTTP request
*/
public boolean isCategoriesURI(AtomRequest req);
/**
* Return true if specified request represents URI of a collection.
* @param req Details of HTTP request
*/
public boolean isCollectionURI(AtomRequest req);
/**
* Return true if specified request represents URI of an Atom entry.
* @param req Details of HTTP request
*/
public boolean isEntryURI(AtomRequest req);
/**
* Return true if specified patrequesthinfo represents media-edit URI.
* @param req Details of HTTP request
*/
public boolean isMediaEditURI(AtomRequest req);
}

View file

@ -1,113 +0,0 @@
/*
* 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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Defines a factory that enables the
* {@link com.sun.syndication.propono.atom.server.AtomServlet} to obtain an
* {@link com.sun.syndication.propono.atom.server.AtomHandler} that handles an Atom request.
*
* <p>To create your own Atom protocol implementation you must sub-class this
* class with your own factory that is capable of creating instances of your
* {@link com.sun.syndication.propono.atom.server.AtomHandler} impementation.</p>
*/
public abstract class AtomHandlerFactory {
private static Log log =
LogFactory.getFactory().getInstance(AtomHandlerFactory.class);
private static final String DEFAULT_PROPERTY_NAME =
"com.sun.syndication.propono.atom.server.AtomHandlerFactory";
private static final String FALLBACK_IMPL_NAME =
"com.sun.syndication.propono.atom.server.impl.FileBasedAtomHandlerFactory";
/*
* <p>Protected constructor to prevent instantiation.
* Use {@link #newInstance()}.</p>
*/
protected AtomHandlerFactory() {
}
/**
* Obtain a new instance of a <code>AtomHandlerFactory</code>. This static
* method creates a new factory instance. This method uses the following
* ordered lookup procedure to determine the <code>AtomHandlerFactory</code>
* implementation class to load:
* <ul>
* <li>
* Use the <code>com.sun.syndication.propono.atom.server.AtomHandlerFactory</code>
* system property.
* </li>
* <li>
* Use the properties file "/propono.properties" in the classpath.
* This configuration file is in standard <code>java.util.Properties</code>
* format and contains the fully qualified name of the implementation
* class with the key being the system property defined above.
*
* The propono.properties file is read only once by Propono and it's
* values are then cached for future use. If the file does not exist
* when the first attempt is made to read from it, no further attempts
* are made to check for its existence. It is not possible to change
* the value of any property in propono.properties after it has been
* read for the first time.
* </li>
* <li>
* If not available, to determine the classname. The Services API will look
* for a classname in the file:
* <code>META-INF/services/com.sun.syndication.AtomHandlerFactory</code>
* in jars available to the runtime.
* </li>
* <li>
* Platform default <code>AtomHandlerFactory</code> instance.
* </li>
* </ul>
*
* Once an application has obtained a reference to a <code>AtomHandlerFactory</code>
* it can use the factory to configure and obtain parser instances.
*
* @return New instance of a <code>AtomHandlerFactory</code>
*
* @throws FactoryConfigurationError if the implementation is not available
* or cannot be instantiated.
*/
public static AtomHandlerFactory newInstance() {
try {
return (AtomHandlerFactory)
FactoryFinder.find(DEFAULT_PROPERTY_NAME, FALLBACK_IMPL_NAME);
} catch (FactoryFinder.ConfigurationError e) {
log.error("ERROR: finding factory", e);
throw new FactoryConfigurationError(e.getException(), e.getMessage());
}
}
/**
* Creates a new instance of a {@link com.sun.syndication.propono.atom.server.AtomHandler}
* using the currently configured parameters.
*
* @return A new instance of a AtomHandler.
*
* @throws AtomConfigurationException if a AtomHandler cannot be created
* which satisfies the configuration requested.
*/
public abstract AtomHandler newAtomHandler(
HttpServletRequest req, HttpServletResponse res);
}

View file

@ -1,95 +0,0 @@
/*
* 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;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Date;
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;
/**
* Represents a media link entry.
*/
public class AtomMediaResource {
private String contentType = null;
private long contentLength = 0;
private InputStream inputStream = null;
private Date lastModified = null;
private static FileTypeMap map = null;
static {
// TODO: figure out why PNG is missing from Java MIME types
map = FileTypeMap.getDefaultFileTypeMap();
if (map instanceof MimetypesFileTypeMap) {
try {
((MimetypesFileTypeMap)map).addMimeTypes("image/png png PNG");
} catch (Exception ignored) {}
}
}
public AtomMediaResource(File resource) throws FileNotFoundException {
contentType = map.getContentType(resource.getName());
contentLength = resource.length();
lastModified = new Date(resource.lastModified());
inputStream = new FileInputStream(resource);
}
public AtomMediaResource(String name, long length, Date lastModified, InputStream is)
throws FileNotFoundException {
this.contentType = map.getContentType(name);
this.contentLength = length;
this.lastModified = lastModified;
this.inputStream = is;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public long getContentLength() {
return contentLength;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
}

View file

@ -1,49 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.server;
import javax.servlet.http.HttpServletResponse;
/**
* Exception to be thrown by <code>AtomHandler</code> implementations in the
* case that a user is not authorized to access a resource.
*/
public class AtomNotAuthorizedException extends AtomException {
/** Construct new exception */
public AtomNotAuthorizedException() {
super();
}
/** Construct new exception with message */
public AtomNotAuthorizedException(String msg) {
super(msg);
}
/** Construct new exception with message and root cause */
public AtomNotAuthorizedException(String msg, Throwable t) {
super(msg, t);
}
/** Construct new exception to wrap root cause*/
public AtomNotAuthorizedException(Throwable t) {
super(t);
}
/** Get HTTP status code of exception (HTTP 403 unauthorized) */
public int getStatus() {
return HttpServletResponse.SC_UNAUTHORIZED;
}
}

View file

@ -1,48 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.server;
import javax.servlet.http.HttpServletResponse;
/**
* Exception thrown by AtomHandler in that case a resource is not found.
*/
public class AtomNotFoundException extends AtomException {
/** Construct new exception */
public AtomNotFoundException() {
super();
}
/** Construct new exception with message */
public AtomNotFoundException(String msg) {
super(msg);
}
/** Construct new exception with message and root cause */
public AtomNotFoundException(String msg, Throwable t) {
super(msg, t);
}
/** Construct new exception with root cause */
public AtomNotFoundException(Throwable t) {
super(t);
}
/** Get HTTP status code associated with exception (404 not found) */
public int getStatus() {
return HttpServletResponse.SC_NOT_FOUND;
}
}

View file

@ -1,139 +0,0 @@
/*
* Copyright 2007 Sun Microsystems, Inc.
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.server;
import java.io.IOException;
import java.io.InputStream;
import java.security.Principal;
import java.util.Enumeration;
import java.util.Map;
/**
* Represents HTTP request to be processed by AtomHandler.
*/
public interface AtomRequest {
/**
* Returns any extra path information associated with the URL the client
* sent when it made this request.
*/
public String getPathInfo();
/**
* Returns the query string that is contained in the request URL after
* the path.
*/
public String getQueryString();
/**
* Returns the login of the user making this request, if the user has
* been authenticated, or null if the user has not been authenticated.
*/
public String getRemoteUser();
/**
* Returns a boolean indicating whether the authenticated user is included
* in the specified logical "role".
*/
public boolean isUserInRole(String arg0);
/**
* Returns a java.security.Principal object containing the name of the
* current authenticated user.
*/
public Principal getUserPrincipal();
/**
* Returns the part of this request's URL from the protocol name up to the
* query string in the first line of the HTTP request.
*/
public String getRequestURI();
/**
* Reconstructs the URL the client used to make the request.
*/
public StringBuffer getRequestURL();
/**
* Returns the length, in bytes, of the request body and made available by
* the input stream, or -1 if the length is not known.
*/
public int getContentLength();
/**
* Returns the MIME type of the body of the request, or null if the type
* is not known. */
public String getContentType();
/**
* Returns the value of a request parameter as a String, or null if the
* parameter does not exist.
*/
public String getParameter(String arg0);
/**
* Returns an Enumeration of String objects containing the names of the
* parameters contained in this request.
*/
public Enumeration getParameterNames();
/**
* Returns an array of String objects containing all of the values the
* given request parameter has, or null if the parameter does not exist.
*/
public String[] getParameterValues(String arg0);
/**
* Returns a java.util.Map of the parameters of this request.
*/
public Map getParameterMap();
/**
* Retrieves the body of the request as binary data using a
* ServletInputStream.
*/
public InputStream getInputStream() throws IOException;
/**
* Returns the value of the specified request header as a long value that
* represents a Date object. */
public long getDateHeader(String arg0);
/**
* Returns the value of the specified request header as a String.
*/
public String getHeader(String arg0);
/**
* Returns all the values of the specified request header as an Enumeration
* of String objects.
*/
public Enumeration getHeaders(String arg0);
/**
* Returns an enumeration of all the header names this request contains.
*/
public Enumeration getHeaderNames();
/**
* Returns the value of the specified request header as an int.
*/
public int getIntHeader(String arg0);
}

View file

@ -1,114 +0,0 @@
/*
* Copyright 2007 Sun Microsystems, Inc.
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.server;
import java.io.IOException;
import java.io.InputStream;
import java.security.Principal;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
* Default request implementation.
*/
public class AtomRequestImpl implements AtomRequest {
private HttpServletRequest wrapped = null;
public AtomRequestImpl(HttpServletRequest wrapped) {
this.wrapped = wrapped;
}
public String getPathInfo() {
return wrapped.getPathInfo() != null ? wrapped.getPathInfo() : "";
}
public String getQueryString() {
return wrapped.getQueryString();
}
public String getRemoteUser() {
return wrapped.getRemoteUser();
}
public boolean isUserInRole(String arg0) {
return wrapped.isUserInRole(arg0);
}
public Principal getUserPrincipal() {
return wrapped.getUserPrincipal();
}
public String getRequestURI() {
return wrapped.getRequestURI();
}
public StringBuffer getRequestURL() {
return wrapped.getRequestURL();
}
public int getContentLength() {
return wrapped.getContentLength();
}
public String getContentType() {
return wrapped.getContentType();
}
public String getParameter(String arg0) {
return wrapped.getParameter(arg0);
}
public Enumeration getParameterNames() {
return wrapped.getParameterNames();
}
public String[] getParameterValues(String arg0) {
return wrapped.getParameterValues(arg0);
}
public Map getParameterMap() {
return wrapped.getParameterMap();
}
public InputStream getInputStream() throws IOException {
return wrapped.getInputStream();
}
public long getDateHeader(String arg0) {
return wrapped.getDateHeader(arg0);
}
public String getHeader(String arg0) {
return wrapped.getHeader(arg0);
}
public Enumeration getHeaders(String arg0) {
return wrapped.getHeaders(arg0);
}
public Enumeration getHeaderNames() {
return wrapped.getHeaderNames();
}
public int getIntHeader(String arg0) {
return wrapped.getIntHeader(arg0);
}
}

View file

@ -1,378 +0,0 @@
/*
* Copyright 2007 Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package com.sun.syndication.propono.atom.server;
import com.sun.syndication.feed.atom.Content;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
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.WireFeedOutput;
import com.sun.syndication.io.impl.Atom10Generator;
import com.sun.syndication.io.impl.Atom10Parser;
import com.sun.syndication.propono.atom.common.AtomService;
import com.sun.syndication.propono.atom.common.Categories;
import com.sun.syndication.propono.utils.Utilities;
import java.io.BufferedReader;
import java.util.Collections;
import java.util.Iterator;
import javax.servlet.ServletConfig;
/**
* Atom Servlet implements Atom protocol by calling an
* {@link com.sun.syndication.propono.atom.server.AtomHandler}
* implementation. This servlet takes care of parsing incoming XML into ROME
* Atom {@link com.sun.syndication.feed.atom.Entry} objects, passing those to the handler and serializing
* to the response the entries and feeds returned by the handler.
*/
public class AtomServlet extends HttpServlet {
/**
* Get feed type support by Servlet, "atom_1.0"
*/
public static final String FEED_TYPE = "atom_1.0";
private static String contextDirPath = null;
private static Log log =
LogFactory.getFactory().getInstance(AtomServlet.class);
static {
Atom10Parser.setResolveURIs(true);
}
//-----------------------------------------------------------------------------
/**
* Create an Atom request handler.
* TODO: make AtomRequestHandler implementation configurable.
*/
private AtomHandler createAtomRequestHandler(
HttpServletRequest request, HttpServletResponse response)
throws ServletException {
AtomHandlerFactory ahf = AtomHandlerFactory.newInstance();
return ahf.newAtomHandler(request, response);
}
//-----------------------------------------------------------------------------
/**
* Handles an Atom GET by calling handler and writing results to response.
*/
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
log.debug("Entering");
AtomHandler handler = createAtomRequestHandler(req, res);
String userName = handler.getAuthenticatedUsername();
if (userName != null) {
AtomRequest areq = new AtomRequestImpl(req);
try {
if (handler.isAtomServiceURI(areq)) {
// return an Atom Service document
AtomService service = handler.getAtomService(areq);
Document doc = service.serviceToDocument();
res.setContentType("application/atomsvc+xml; charset=utf-8");
Writer writer = res.getWriter();
XMLOutputter outputter = new XMLOutputter();
outputter.setFormat(Format.getPrettyFormat());
outputter.output(doc, writer);
writer.close();
res.setStatus(HttpServletResponse.SC_OK);
}
else if (handler.isCategoriesURI(areq)) {
Categories cats = handler.getCategories(areq);
res.setContentType("application/xml");
Writer writer = res.getWriter();
Document catsDoc = new Document();
catsDoc.setRootElement(cats.categoriesToElement());
XMLOutputter outputter = new XMLOutputter();
outputter.output(catsDoc, writer);
writer.close();
res.setStatus(HttpServletResponse.SC_OK);
}
else if (handler.isCollectionURI(areq)) {
// return a collection
Feed col = handler.getCollection(areq);
col.setFeedType(FEED_TYPE);
WireFeedOutput wireFeedOutput = new WireFeedOutput();
Document feedDoc = wireFeedOutput.outputJDom(col);
res.setContentType("application/atom+xml; charset=utf-8");
Writer writer = res.getWriter();
XMLOutputter outputter = new XMLOutputter();
outputter.setFormat(Format.getPrettyFormat());
outputter.output(feedDoc, writer);
writer.close();
res.setStatus(HttpServletResponse.SC_OK);
}
else if (handler.isEntryURI(areq)) {
// return an entry
Entry entry = handler.getEntry(areq);
if (entry != null) {
res.setContentType("application/atom+xml; type=entry; charset=utf-8");
Writer writer = res.getWriter();
Atom10Generator.serializeEntry(entry, writer);
writer.close();
} else {
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
}
else if (handler.isMediaEditURI(areq)) {
AtomMediaResource entry = handler.getMediaResource(areq);
res.setContentType(entry.getContentType());
res.setContentLength((int)entry.getContentLength());
Utilities.copyInputToOutput(entry.getInputStream(), res.getOutputStream());
res.getOutputStream().flush();
res.getOutputStream().close();
}
else {
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
} catch (AtomException ae) {
res.sendError(ae.getStatus(), ae.getMessage());
log.debug("ERROR processing GET", ae);
} catch (Exception e) {
res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
log.debug("ERROR processing GET", e);
}
} else {
res.setHeader("WWW-Authenticate", "BASIC realm=\"AtomPub\"");
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
log.debug("Exiting");
}
//-----------------------------------------------------------------------------
/**
* Handles an Atom POST by calling handler to identify URI, reading/parsing
* data, calling handler and writing results to response.
*/
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
log.debug("Entering");
AtomHandler handler = createAtomRequestHandler(req, res);
String userName = handler.getAuthenticatedUsername();
if (userName != null) {
AtomRequest areq = new AtomRequestImpl(req);
try {
if (handler.isCollectionURI(areq)) {
if (req.getContentType().startsWith("application/atom+xml")) {
// parse incoming entry
Entry entry = Atom10Parser.parseEntry(new BufferedReader(
new InputStreamReader(req.getInputStream(), "UTF-8")), null);
// call handler to post it
Entry newEntry = handler.postEntry(areq, entry);
// set Location and Content-Location headers
for (Iterator it = newEntry.getOtherLinks().iterator(); it.hasNext();) {
Link link = (Link) it.next();
if ("edit".equals(link.getRel())) {
res.addHeader("Location", link.getHrefResolved());
break;
}
}
for (Iterator it = newEntry.getAlternateLinks().iterator(); it.hasNext();) {
Link link = (Link) it.next();
if ("alternate".equals(link.getRel())) {
res.addHeader("Content-Location", link.getHrefResolved());
break;
}
}
// write entry back out to response
res.setStatus(HttpServletResponse.SC_CREATED);
res.setContentType("application/atom+xml; type=entry; charset=utf-8");
Writer writer = res.getWriter();
Atom10Generator.serializeEntry(newEntry, writer);
writer.close();
} else if (req.getContentType() != null) {
// get incoming title and slug from HTTP header
String title = areq.getHeader("Title");
// create new entry for resource, set title and type
Entry resource = new Entry();
resource.setTitle(title);
Content content = new Content();
content.setType(areq.getContentType());
resource.setContents(Collections.singletonList(content));
// hand input stream off to hander to post file
Entry newEntry = handler.postMedia(areq, resource);
// set Location and Content-Location headers
for (Iterator it = newEntry.getOtherLinks().iterator(); it.hasNext();) {
Link link = (Link) it.next();
if ("edit".equals(link.getRel())) {
res.addHeader("Location", link.getHrefResolved());
break;
}
}
for (Iterator it = newEntry.getAlternateLinks().iterator(); it.hasNext();) {
Link link = (Link) it.next();
if ("alternate".equals(link.getRel())) {
res.addHeader("Content-Location", link.getHrefResolved());
break;
}
}
res.setStatus(HttpServletResponse.SC_CREATED);
res.setContentType("application/atom+xml; type=entry; charset=utf-8");
Writer writer = res.getWriter();
Atom10Generator.serializeEntry(newEntry, writer);
writer.close();
} else {
res.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
"No content-type specified in request");
}
} else {
res.sendError(HttpServletResponse.SC_NOT_FOUND,
"Invalid collection specified in request");
}
} catch (AtomException ae) {
res.sendError(ae.getStatus(), ae.getMessage());
log.debug("ERROR processing POST", ae);
} catch (Exception e) {
res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
log.debug("ERROR processing POST", e);
}
} else {
res.setHeader("WWW-Authenticate", "BASIC realm=\"AtomPub\"");
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
log.debug("Exiting");
}
//-----------------------------------------------------------------------------
/**
* Handles an Atom PUT by calling handler to identify URI, reading/parsing
* data, calling handler and writing results to response.
*/
protected void doPut(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
log.debug("Entering");
AtomHandler handler = createAtomRequestHandler(req, res);
String userName = handler.getAuthenticatedUsername();
if (userName != null) {
AtomRequest areq = new AtomRequestImpl(req);
try {
if (handler.isEntryURI(areq)) {
// parse incoming entry
Entry unsavedEntry = Atom10Parser.parseEntry(new BufferedReader(
new InputStreamReader(req.getInputStream(), "UTF-8")), null);
// call handler to put entry
handler.putEntry(areq, unsavedEntry);
res.setStatus(HttpServletResponse.SC_OK);
} else if (handler.isMediaEditURI(areq)) {
// hand input stream to handler
handler.putMedia(areq);
res.setStatus(HttpServletResponse.SC_OK);
} else {
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
} catch (AtomException ae) {
res.sendError(ae.getStatus(), ae.getMessage());
log.debug("ERROR processing PUT", ae);
} catch (Exception e) {
res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
log.debug("ERROR processing PUT", e);
}
} else {
res.setHeader("WWW-Authenticate", "BASIC realm=\"AtomPub\"");
// Wanted to use sendError() here but Tomcat sends 403 forbidden
// when I do that, so sticking with setStatus() for time being.
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
log.debug("Exiting");
}
//-----------------------------------------------------------------------------
/**
* Handle Atom DELETE by calling appropriate handler.
*/
protected void doDelete(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
log.debug("Entering");
AtomHandler handler = createAtomRequestHandler(req, res);
String userName = handler.getAuthenticatedUsername();
if (userName != null) {
AtomRequest areq = new AtomRequestImpl(req);
try {
if (handler.isEntryURI(areq)) {
handler.deleteEntry(areq);
res.setStatus(HttpServletResponse.SC_OK);
}
else {
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
} catch (AtomException ae) {
res.sendError(ae.getStatus(), ae.getMessage());
log.debug("ERROR processing DELETE", ae);
} catch (Exception e) {
res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
log.debug("ERROR processing DELETE", e);
}
} else {
res.setHeader("WWW-Authenticate", "BASIC realm=\"AtomPub\"");
// Wanted to use sendError() here but Tomcat sends 403 forbidden
// when I do that, so sticking with setStatus() for time being.
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
log.debug("Exiting");
}
/**
* Initialize servlet.
*/
public void init( ServletConfig config ) throws ServletException {
super.init( config );
contextDirPath = getServletContext().getRealPath("/");
}
/**
* Get absolute path to Servlet context directory.
*/
public static String getContextDirPath() {
return contextDirPath;
}
}

View file

@ -1,106 +0,0 @@
/*
* 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;
/**
* Thrown when a problem with configuration with the
* {@link com.sun.syndication.propono.atom.server.AtomHandlerFactory} exists.
* This error will typically be thrown when the class of a parser factory
* specified in the system properties cannot be found or instantiated.
*/
public class FactoryConfigurationError extends Error {
/**
* <code>Exception</code> that represents the error.
*/
private Exception exception;
/**
* Create a new <code>FactoryConfigurationError</code> with no
* detail mesage.
*/
public FactoryConfigurationError() {
super();
this.exception = null;
}
/**
* Create a new <code>FactoryConfigurationError</code> with
* the <code>String </code> specified as an error message.
*
* @param msg The error message for the exception.
*/
public FactoryConfigurationError(String msg) {
super(msg);
this.exception = null;
}
/**
* Create a new <code>FactoryConfigurationError</code> with a
* given <code>Exception</code> base cause of the error.
*
* @param e The exception to be encapsulated in a
* FactoryConfigurationError.
*/
public FactoryConfigurationError(Exception e) {
super(e.toString());
this.exception = e;
}
/**
* Create a new <code>FactoryConfigurationError</code> with the
* given <code>Exception</code> base cause and detail message.
*
* @param e The exception to be encapsulated in a
* FactoryConfigurationError
* @param msg The detail message.
*/
public FactoryConfigurationError(Exception e, String msg) {
super(msg);
this.exception = e;
}
/**
* Return the message (if any) for this error . If there is no
* message for the exception and there is an encapsulated
* exception then the message of that exception, if it exists will be
* returned. Else the name of the encapsulated exception will be
* returned.
*
* @return The error message.
*/
public String getMessage() {
String message = super.getMessage();
if (message == null && exception != null) {
return exception.getMessage();
}
return message;
}
/**
* Return the actual exception (if any) that caused this exception to
* be raised.
*
* @return The encapsulated exception, or null if there is none.
*/
public Exception getException() {
return exception;
}
}

View file

@ -1,280 +0,0 @@
/*
* 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;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
/**
* Find {@link com.sun.syndication.propono.atom.server.AtomHandlerFactory} based on properties files.
*/
class FactoryFinder {
private static boolean debug = false;
static Properties cacheProps= new Properties();
static SecuritySupport ss = new SecuritySupport() ;
static boolean firstTime = true;
private static void dPrint(String msg) {
if (debug) {
System.err.println("Propono: " + msg);
}
}
/**
* Create an instance of a class using the specified ClassLoader and
* optionally fall back to the current ClassLoader if not found.
*
* @param className Name of the concrete class corresponding to the
* service provider
*
* @param cl ClassLoader to use to load the class, null means to use
* the bootstrap ClassLoader
*
* @param doFallback true if the current ClassLoader should be tried as
* a fallback if the class is not found using cl
*/
private static Object newInstance(
String className, ClassLoader cl, boolean doFallback)
throws ConfigurationError {
try {
Class providerClass;
if (cl == null) {
// If classloader is null Use the bootstrap ClassLoader.
// Thus Class.forName(String) will use the current
// ClassLoader which will be the bootstrap ClassLoader.
providerClass = Class.forName(className);
} else {
try {
providerClass = cl.loadClass(className);
} catch (ClassNotFoundException x) {
if (doFallback) {
// Fall back to current classloader
cl = FactoryFinder.class.getClassLoader();
providerClass = cl.loadClass(className);
} else {
throw x;
}
}
}
Object instance = providerClass.newInstance();
dPrint("created new instance of " + providerClass +
" using ClassLoader: " + cl);
return instance;
} catch (ClassNotFoundException x) {
throw new ConfigurationError(
"Provider " + className + " not found", x);
} catch (Exception x) {
throw new ConfigurationError(
"Provider " + className + " could not be instantiated: " + x, x);
}
}
/**
* Finds the implementation Class object in the specified order. Main
* entry point.
* @return Class object of factory, never null
*
* @param factoryId Name of the factory to find, same as
* a property name
* @param fallbackClassName Implementation class name, if nothing else
* is found. Use null to mean no fallback.
*
* Package private so this code can be shared.
*/
static Object find(String factoryId, String fallbackClassName)
throws ConfigurationError {
// Figure out which ClassLoader to use for loading the provider
// class. If there is a Context ClassLoader then use it.
ClassLoader classLoader = ss.getContextClassLoader();
if (classLoader == null) {
// if we have no Context ClassLoader
// so use the current ClassLoader
classLoader = FactoryFinder.class.getClassLoader();
}
dPrint("find factoryId =" + factoryId);
// Use the system property first
try {
String systemProp = ss.getSystemProperty(factoryId);
if( systemProp!=null) {
dPrint("found system property, value=" + systemProp);
return newInstance(systemProp, classLoader, true );
}
} catch (SecurityException se) {
//if first option fails due to any reason we should try next option in the
//look up algorithm.
}
// try to read from /propono.properties
try {
String javah = ss.getSystemProperty("java.home");
String configFile = "/propono.properties";
String factoryClassName = null;
if(firstTime){
synchronized(cacheProps){
if (firstTime) {
try {
InputStream is = FactoryFinder.class.getResourceAsStream(configFile);
firstTime = false;
if (is != null) {
dPrint("Read properties file: " + configFile);
cacheProps.load(is);
}
} catch (Exception intentionallyIgnored) {}
}
}
}
factoryClassName = cacheProps.getProperty(factoryId);
if(factoryClassName != null){
dPrint("found in $java.home/propono.properties, value=" + factoryClassName);
return newInstance(factoryClassName, classLoader, true);
}
} catch(Exception ex) {
if( debug ) ex.printStackTrace();
}
// Try Jar Service Provider Mechanism
Object provider = findJarServiceProvider(factoryId);
if (provider != null) {
return provider;
}
if (fallbackClassName == null) {
throw new ConfigurationError(
"Provider for " + factoryId + " cannot be found", null);
}
dPrint("loaded from fallback value: " + fallbackClassName);
return newInstance(fallbackClassName, classLoader, true);
}
/*
* Try to find provider using Jar Service Provider Mechanism
*
* @return instance of provider class if found or null
*/
private static Object findJarServiceProvider(String factoryId)
throws ConfigurationError {
String serviceId = "META-INF/services/" + factoryId;
InputStream is = null;
// First try the Context ClassLoader
ClassLoader cl = ss.getContextClassLoader();
if (cl != null) {
is = ss.getResourceAsStream(cl, serviceId);
// If no provider found then try the current ClassLoader
if (is == null) {
cl = FactoryFinder.class.getClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
}
} else {
// No Context ClassLoader, try the current
// ClassLoader
cl = FactoryFinder.class.getClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
}
if (is == null) {
// No provider found
return null;
}
dPrint("found jar resource=" + serviceId +
" using ClassLoader: " + cl);
// Read the service provider name in UTF-8 as specified in
// the jar spec. Unfortunately this fails in Microsoft
// VJ++, which does not implement the UTF-8
// encoding. Theoretically, we should simply let it fail in
// that case, since the JVM is obviously broken if it
// doesn't support such a basic standard. But since there
// are still some users attempting to use VJ++ for
// development, we have dropped in a fallback which makes a
// second attempt using the platform's default encoding. In
// VJ++ this is apparently ASCII, which is a subset of
// UTF-8... and since the strings we'll be reading here are
// also primarily limited to the 7-bit ASCII range (at
// least, in English versions), this should work well
// enough to keep us on the air until we're ready to
// officially decommit from VJ++. [Edited comment from
// jkesselm]
BufferedReader rd;
try {
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
} catch (java.io.UnsupportedEncodingException e) {
rd = new BufferedReader(new InputStreamReader(is));
}
String factoryClassName = null;
try {
// XXX Does not handle all possible input as specified by the
// Jar Service Provider specification
factoryClassName = rd.readLine();
rd.close();
} catch (IOException x) {
// No provider found
return null;
}
if (factoryClassName != null &&
! "".equals(factoryClassName)) {
dPrint("found in resource, value="
+ factoryClassName);
// Note: here we do not want to fall back to the current
// ClassLoader because we want to avoid the case where the
// resource file was found using one ClassLoader and the
// provider class was instantiated using a different one.
return newInstance(factoryClassName, cl, false);
}
// No provider found
return null;
}
static class ConfigurationError extends Error {
private Exception exception;
/**
* Construct a new instance with the specified detail string and
* exception.
*/
ConfigurationError(String msg, Exception x) {
super(msg);
this.exception = x;
}
Exception getException() {
return exception;
}
}
}

View file

@ -1,90 +0,0 @@
/*
* 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;
import java.security.*;
import java.net.*;
import java.io.*;
import java.util.*;
/**
* This class is duplicated for each subpackage, it is package private and
* therefore is not exposed as part of the public API.
*/
class SecuritySupport {
ClassLoader getContextClassLoader() {
return (ClassLoader)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (SecurityException ex) { }
return cl;
}
});
}
String getSystemProperty(final String propName) {
return (String)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty(propName);
}
});
}
FileInputStream getFileInputStream(final File file)
throws FileNotFoundException {
try {
return (FileInputStream)
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws FileNotFoundException {
return new FileInputStream(file);
}
});
} catch (PrivilegedActionException e) {
throw (FileNotFoundException)e.getException();
}
}
InputStream getResourceAsStream(final ClassLoader cl,
final String name) {
return (InputStream)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
InputStream ris;
if (cl == null) {
ris = ClassLoader.getSystemResourceAsStream(name);
} else {
ris = cl.getResourceAsStream(name);
}
return ris;
}
});
}
boolean doesFileExist(final File f) {
return ((Boolean)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return new Boolean(f.exists());
}
})).booleanValue();
}
}

View file

@ -1,443 +0,0 @@
/*
* 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 com.sun.syndication.propono.atom.server.AtomMediaResource;
import org.apache.commons.codec.binary.Base64;
import com.sun.syndication.propono.atom.server.AtomHandler;
import com.sun.syndication.propono.atom.server.AtomException;
import com.sun.syndication.propono.atom.server.AtomServlet;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Feed;
import com.sun.syndication.propono.atom.common.AtomService;
import com.sun.syndication.propono.atom.common.Categories;
import com.sun.syndication.propono.atom.server.AtomRequest;
import java.io.File;
import java.util.StringTokenizer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
/**
* File-based {@link com.sun.syndication.propono.atom.server.AtomHandler}
* implementation that stores entries and media-entries to disk. Implemented
* using {@link com.sun.syndication.propono.atom.server.impl.FileBasedAtomService}.
*/
public class FileBasedAtomHandler implements AtomHandler {
private static Log log =
LogFactory.getFactory().getInstance(FileBasedAtomHandler.class);
private static String fileStoreDir = null;
private String userName = null;
private String atomProtocolURL = null;
private String contextURI = null;
private String uploadurl = null;
private FileBasedAtomService service = null;
/**
* Construct handler to handle one request.
* @param req Request to be handled.
*/
public FileBasedAtomHandler( HttpServletRequest req ) {
this(req, AtomServlet.getContextDirPath());
}
/**
* Contruct handler for one request, using specified file storage directory.
* @param req Request to be handled.
* @param uploaddir File storage upload dir.
*/
public FileBasedAtomHandler(HttpServletRequest req, String uploaddir) {
log.debug("ctor");
userName = authenticateBASIC(req);
atomProtocolURL = req.getScheme() + "://" + req.getServerName() + ":"
+ req.getServerPort() + req.getContextPath() + req.getServletPath();
contextURI = req.getScheme() + "://" + req.getServerName() + ":"
+ req.getServerPort() + req.getContextPath();
try {
service = new FileBasedAtomService(userName, uploaddir,
contextURI, req.getContextPath(), req.getServletPath());
} catch (Throwable t) {
throw new RuntimeException("ERROR creating FileBasedAtomService", t);
}
}
/**
* Method used for validating user. Developers can overwrite this method
* and use credentials stored in Database or LDAP to confirm if the user is
* allowed to access this service.
* @param login user submitted login id
* @param password user submitted password
*/
public boolean validateUser(String login, String password) {
return true;
}
/**
* Get username of authenticated user
* @return User name.
*/
public String getAuthenticatedUsername() {
// For now return userName as the login id entered for authorization
return userName;
}
/**
* Get base URI of Atom protocol implementation.
* @return Base URI of Atom protocol implemenation.
*/
public String getAtomProtocolURL( ) {
if ( atomProtocolURL == null ) {
return "app";
} else {
return atomProtocolURL;
}
}
/**
* Return introspection document
* @throws com.sun.syndication.propono.atom.server.AtomException Unexpected exception.
* @return AtomService object with workspaces and collections.
*/
public AtomService getAtomService(AtomRequest areq) throws AtomException {
return service;
}
/**
* Returns null because we use in-line categories.
* @throws com.sun.syndication.propono.atom.server.AtomException Unexpected exception.
* @return Categories object
*/
public Categories getCategories(AtomRequest areq) throws AtomException {
log.debug("getCollection");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
return (Categories)col.getCategories(true).get(0);
}
/**
* Get collection specified by pathinfo.
* @param areq Details of HTTP request
* @return ROME feed representing collection.
* @throws com.sun.syndication.propono.atom.server.AtomException Invalid collection or other exception.
*/
public Feed getCollection(AtomRequest areq) throws AtomException {
log.debug("getCollection");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
return col.getFeedDocument();
}
/**
* Create a new entry specified by pathInfo and posted entry. We save the
* submitted Atom entry verbatim, but we do set the id and reset the update
* time.
*
* @param entry Entry to be added to collection.
* @param areq Details of HTTP request
* @throws com.sun.syndication.propono.atom.server.AtomException On invalid collection or other error.
* @return Entry as represented on server.
*/
public Entry postEntry(AtomRequest areq, Entry entry) throws AtomException {
log.debug("postEntry");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
try {
return col.addEntry(entry);
} catch (Exception fe) {
fe.printStackTrace();
throw new AtomException( fe );
}
}
/**
* Get entry specified by pathInfo.
* @param areq Details of HTTP request
* @throws com.sun.syndication.propono.atom.server.AtomException On invalid pathinfo or other error.
* @return ROME Entry object.
*/
public Entry getEntry(AtomRequest areq) throws AtomException {
log.debug("getEntry");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
String fileName = pathInfo[2];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
try {
return col.getEntry(fileName);
} catch (Exception re) {
if (re instanceof AtomException) throw (AtomException)re;
throw new AtomException("ERROR: getting entry", re);
}
}
/**
* Update entry specified by pathInfo and posted entry.
*
* @param entry
* @param areq Details of HTTP request
* @throws com.sun.syndication.propono.atom.server.AtomException
*/
public void putEntry(AtomRequest areq, Entry entry) throws AtomException {
log.debug("putEntry");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
String fileName = pathInfo[2];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
try {
col.updateEntry(entry, fileName);
} catch ( Exception fe ) {
throw new AtomException( fe );
}
}
/**
* Delete entry specified by pathInfo.
* @param areq Details of HTTP request
*/
public void deleteEntry(AtomRequest areq) throws AtomException {
log.debug("deleteEntry");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
String fileName = pathInfo[2];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
try {
col.deleteEntry(fileName);
} catch (Exception e) {
String msg = "ERROR in atom.deleteResource";
log.error(msg,e);
throw new AtomException(msg);
}
}
/**
* Store media data in collection specified by pathInfo, create an Atom
* media-link entry to store metadata for the new media file and return
* that entry to the caller.
* @param areq Details of HTTP request
* @param entry New entry initialzied with only title and content type
* @return Location URL of new media entry
*/
public Entry postMedia(AtomRequest areq, Entry entry) throws AtomException {
// get incoming slug from HTTP header
String slug = areq.getHeader("Slug");
if (log.isDebugEnabled()) {
log.debug("postMedia - title: "+entry.getTitle()+" slug:"+slug);
}
try {
File tempFile = null;
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
try {
col.addMediaEntry(entry, slug, areq.getInputStream());
} catch (Exception e) {
e.printStackTrace();
String msg = "ERROR reading posted file";
log.error(msg,e);
throw new AtomException(msg, e);
} finally {
if (tempFile != null) tempFile.delete();
}
} catch (Exception re) {
throw new AtomException("ERROR: posting media");
}
return entry;
}
/**
* Update the media file part of a media-link entry.
* @param areq Details of HTTP request
* Assuming pathInfo of form /user-name/resource/name
*/
public void putMedia(AtomRequest areq) throws AtomException {
log.debug("putMedia");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
String fileName = pathInfo[3];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
try {
col.updateMediaEntry(fileName, areq.getContentType(), areq.getInputStream());
} catch (Exception re) {
throw new AtomException("ERROR: posting media");
}
}
public AtomMediaResource getMediaResource(AtomRequest areq) throws AtomException {
log.debug("putMedia");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
String handle = pathInfo[0];
String collection = pathInfo[1];
String fileName = pathInfo[3];
FileBasedCollection col = service.findCollectionByHandle(handle, collection);
try {
return col.getMediaResource(fileName);
} catch (Exception re) {
throw new AtomException("ERROR: posting media");
}
}
/**
* Return true if specified pathinfo represents URI of service doc.
*/
public boolean isAtomServiceURI(AtomRequest areq) {
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
if (pathInfo.length==0) return true;
return false;
}
/**
* Return true if specified pathinfo represents URI of category doc.
*/
public boolean isCategoriesURI(AtomRequest areq) {
log.debug("isCategoriesDocumentURI");
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
if (pathInfo.length == 3 && "categories".equals(pathInfo[2])) {
return true;
}
return false;
}
/**
* Return true if specified pathinfo represents URI of a collection.
*/
public boolean isCollectionURI(AtomRequest areq) {
log.debug("isCollectionURI");
// workspace/collection-plural
// if length is 2 and points to a valid collection then YES
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
if (pathInfo.length == 2) {
String handle = pathInfo[0];
String collection = pathInfo[1];
if (service.findCollectionByHandle(handle, collection) != null) {
return true;
}
}
return false;
}
/**
* Return true if specified pathinfo represents URI of an Atom entry.
*/
public boolean isEntryURI(AtomRequest areq) {
log.debug("isEntryURI");
// workspace/collection-singular/fsid
// if length is 3 and points to a valid collection then YES
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
if (pathInfo.length == 3) {
String handle = pathInfo[0];
String collection = pathInfo[1];
if (service.findCollectionByHandle(handle, collection) != null) {
return true;
}
}
return false;
}
/**
* Return true if specified pathinfo represents media-edit URI.
*/
public boolean isMediaEditURI(AtomRequest areq) {
log.debug("isMediaEditURI");
// workspace/collection-singular/fsid/media/fsid
// if length is 4, points to a valid collection and fsid is mentioned twice then YES
String[] pathInfo = StringUtils.split(areq.getPathInfo(),"/");
if (pathInfo.length == 4) {
String handle = pathInfo[0];
String collection = pathInfo[1];
String media = pathInfo[2];
String fsid = pathInfo[3];
if (service.findCollectionByHandle(handle, collection) != null && media.equals("media")) {
return true;
}
}
return false;
}
/**
* BASIC authentication.
*/
public String authenticateBASIC(HttpServletRequest request) {
log.debug("authenticateBASIC");
boolean valid = false;
String userID = null;
String password = null;
try {
String authHeader = request.getHeader("Authorization");
if (authHeader != null) {
StringTokenizer st = new StringTokenizer(authHeader);
if (st.hasMoreTokens()) {
String basic = st.nextToken();
if (basic.equalsIgnoreCase("Basic")) {
String credentials = st.nextToken();
String userPass = new String(Base64.decodeBase64(credentials.getBytes()));
int p = userPass.indexOf(":");
if (p != -1) {
userID = userPass.substring(0, p);
password = userPass.substring(p+1);
// Validate the User.
valid = validateUser( userID, password );
}
}
}
}
} catch (Exception e) {
log.debug(e);
}
if (valid) {
//For now assume userID as userName
return userID;
}
return null;
}
}

View file

@ -1,37 +0,0 @@
/*
* 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 com.sun.syndication.propono.atom.server.AtomHandlerFactory;
import com.sun.syndication.propono.atom.server.AtomHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Extends {@link com.sun.syndication.propono.atom.server.AtomHandlerFactory} to create and return
* {@link com.sun.syndication.propono.atom.server.impl.FileBasedAtomHandler}.
*/
public class FileBasedAtomHandlerFactory extends AtomHandlerFactory {
/**
* Create new AtomHandler.
*/
public AtomHandler newAtomHandler(
HttpServletRequest req, HttpServletResponse res ) {
return new FileBasedAtomHandler(req);
}
}

View file

@ -1,188 +0,0 @@
/*
* 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 com.sun.syndication.propono.atom.common.AtomService;
import com.sun.syndication.propono.utils.Utilities;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
/**
* File based Atom service.
* Supports one workspace per user.
* Collections in workspace are defined in /propono.properties, for example:
*
* <pre>
* # Define list of collections to be offered
* propono.atomserver.filebased.collections=entries,gifimages
*
* # Defines 'entries' collection, accepts entries
* propono.atomserver.filebased.collection.entries.title=Entries
* propono.atomserver.filebased.collection.entries.singular=entry
* propono.atomserver.filebased.collection.entries.plural=entries
* propono.atomserver.filebased.collection.entries.accept=application/atom+xml;type=entry
* propono.atomserver.filebased.collection.entries.categories=general,category1,category2
*
* # Defines 'gifimages' collection, accepts only GIF files
* propono.atomserver.filebased.collection.gifimages.title=GIF Images
* propono.atomserver.filebased.collection.gifimages.singular=gif
* propono.atomserver.filebased.collection.gifimages.plural=gifs
* propono.atomserver.filebased.collection.gifimages.accept=image/gif
* propono.atomserver.filebased.collection.gifimages.categories=general,category1,category2
* </pre>
*
* If no such properties are found, then service will fall back to two
* collections: 'entries' for Atom entries and 'resources' for any content-type.
*
*
* <p><b>URI structure used for accessing collections and entries</b></p>
*
* <p>Collection feed (URI allows GET to get collection, POST to add to it)<br/>
* <code>[servlet-context-uri]/app/[workspace-handle]/[collection-plural] </code>
* </p>
*
* <p>Collection entry (URI allows GET, PUT and DELETE)<br/>
* <code>[servlet-context-uri]/app/[workspace-handle]/[collection-singular]/[entryid] </code>
* </p>
*
* <p>Collection entry media (URI allows GET, PUT and DELETE)<br/>
* <code>[servlet-context-uri]/app/[workspace-handle]/[collection-singular]/media/[entryid]</code>
* </p>
*
* <p>Categories URI if not using inline categories (URI allows GET)<br/>
* <code>[servlet-context-uri]/app/[workspace-handle]/[collection-plural]/categories</code>
* </p>
*
*
* <p><b>Directory structure used to store collections and entries</b></p>
*
* <p>Collection feed (kept constantly up to date)<br/>
* <code>[servlet-context-dir]/[workspace-handle]/[collection-plural]/feed.xml</code>
* </p>
*
* <p>Collection entry (individual entries also stored as entry.xml files)<br/>
* <code>[servlet-context-dir]/[workspace-handle]/[collection-plural]/id/entry.xml</code>
* </p>
*
* <p>Collection entry media (media file stored under entry directory)<br/>
* <code>[servlet-context-dir]/[workspace-handle]/[collection-plural]/id/media/id</code>
* </p>
*/
public class FileBasedAtomService extends AtomService {
private Map workspaceMap = new TreeMap();
private Map collectionMap = new TreeMap();
private static Properties cacheProps = new Properties();
private boolean firstTime = true;
/**
* Creates a new instance of FileBasedAtomService.
*/
public FileBasedAtomService(
String userName, String baseDir, String contextURI, String contextPath, String servletPath) throws Exception {
String workspaceHandle = userName;
// One workspace per user
FileBasedWorkspace workspace = new FileBasedWorkspace(workspaceHandle, baseDir);
workspaceMap.put(userName, workspace);
if (firstTime) {
synchronized(cacheProps) {
InputStream is = getClass().getResourceAsStream("/propono.properties");
if (is != null) cacheProps.load(is);
firstTime = false;
}
}
// can't find propono.properties, so use system props instead
if (cacheProps == null) cacheProps = System.getProperties();
String relativeURIsString = cacheProps.getProperty(
"propono.atomserver.filebased.relativeURIs");
boolean relativeURIs = "true".equals(relativeURIsString);
String inlineCategoriesString = cacheProps.getProperty(
"propono.atomserver.filebased.inlineCategories");
boolean inlineCategories = "true".equals(inlineCategoriesString);
String colnames = cacheProps.getProperty("propono.atomserver.filebased.collections");
if (colnames != null) {
// collections specified in propono.properties, use those
String[] colarray = Utilities.stringToStringArray(colnames,",");
for (int i=0; i<colarray.length; i++) {
String prefix = "propono.atomserver.filebased.collection." + colarray[i] + ".";
String collectionTitle = cacheProps.getProperty(prefix + "title");
String collectionSingular = cacheProps.getProperty(prefix + "singular");
String collectionPlural = cacheProps.getProperty(prefix + "plural");
String collectionAccept = cacheProps.getProperty(prefix + "accept");
String catNamesString = cacheProps.getProperty(prefix + "categories");
String[] catNames = Utilities.stringToStringArray(catNamesString, ",");
FileBasedCollection entries = new FileBasedCollection(
collectionTitle, workspaceHandle,
collectionPlural, collectionSingular, collectionAccept,
inlineCategories, catNames,
relativeURIs, contextURI, contextPath, servletPath, baseDir);
workspace.addCollection(entries);
// want to be able to look up collection by singular and plural names
collectionMap.put(workspaceHandle + "|" + collectionSingular, entries);
collectionMap.put(workspaceHandle + "|" + collectionPlural, entries);
}
} else {
// Fallback to two collections. One collection for accepting entries
// and other collection for other ( resources/uploaded images etc.)
String[] catNames = new String[] {"general", "category1", "category2"};
FileBasedCollection entries = new FileBasedCollection(
"Entries", workspaceHandle,
"entries", "entry", "application/atom+xml;type=entry",
inlineCategories, catNames,
relativeURIs, contextURI, contextPath, servletPath, baseDir);
workspace.addCollection(entries);
// want to be able to look up collection by singular and plural names
collectionMap.put(workspaceHandle + "|entry", entries);
collectionMap.put(workspaceHandle + "|entries", entries);
FileBasedCollection resources = new FileBasedCollection(
"Resources", workspaceHandle,
"resources", "resource", "*/*",
inlineCategories, catNames,
relativeURIs, contextURI, contextPath, servletPath, baseDir);
// want to be able to look up collection by singular and plural names
workspace.addCollection(resources);
collectionMap.put(workspaceHandle + "|resource", resources);
collectionMap.put(workspaceHandle + "|resources", resources);
}
getWorkspaces().add(workspace);
}
/**
* Find workspace by handle, returns null of not found.
*/
FileBasedWorkspace findWorkspaceByHandle(String handle) {
return (FileBasedWorkspace)workspaceMap.get(handle);
}
FileBasedCollection findCollectionByHandle(String handle, String collection) {
return (FileBasedCollection)collectionMap.get(handle+"|"+collection);
}
}

View file

@ -1,837 +0,0 @@
/*
* 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<catNames.length; i++) {
Category cat = new Category();
cat.setTerm(catNames[i]);
cats.addCategory(cat);
}
} else {
cats.setHref(getCategoriesURI());
}
return Collections.singletonList(cats);
}
/**
* Get list of one Categories object containing categories allowed by collection,
* returns in-line categories if collection set to use in-line categories.
*/
public List getCategories() {
return getCategories(inlineCats);
}
/**
* Add entry to collection.
* @param entry Entry to be added to collection. Entry will be saved to disk in a
* directory under the collection's directory and the path will follow the
* pattern [collection-plural]/[entryid]/entry.xml. The entry will be added
* to the collection's feed in [collection-plural]/feed.xml.
* @throws java.lang.Exception On error.
* @return Entry as it exists on the server.
*/
public Entry addEntry(Entry entry) throws Exception {
synchronized (FileStore.getFileStore()) {
Feed f = getFeedDocument();
String fsid = FileStore.getFileStore().getNextId();
updateTimestamps(entry);
// Save entry to file
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 feed file
updateEntryAppLinks(entry, fsid, false);
updateFeedDocumentWithNewEntry(f, entry);
return entry;
}
}
/**
* Add media entry to collection. Accepts a media file to be added to collection.
* The file will be saved to disk in a directory under the collection's directory
* and the path will follow the pattern <code>[collection-plural]/[entryid]/media/[entryid]</code>.
* An Atom entry will be created to store metadata for the entry and it will exist
* at the path <code>[collection-plural]/[entryid]/entry.xml</code>.
* 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<f.getEntries().size(); i++) {
Entry entry = (Entry)f.getEntries().get(i);
AppModule mod = (AppModule)entry.getModule(AppModule.URI);
AppModule newMod = (AppModule)e.getModule(AppModule.URI);
if (newMod.getEdited().before(mod.getEdited())) {
f.getEntries().add(i, e);
inserted = true;
break;
}
}
if (!inserted) {
f.getEntries().add(0, e);
}
updateFeedDocument(f);
}
private void updateFeedDocumentRemovingEntry(Feed f, String id) throws AtomException {
Entry e = findEntry("urn:uuid:" + id, f);
f.getEntries().remove(e);
updateFeedDocument(f);
}
private void updateFeedDocumentWithExistingEntry(Feed f, Entry e) throws AtomException {
Entry old = findEntry(e.getId(), f);
f.getEntries().remove(old);
boolean inserted = false;
for (int i=0; i<f.getEntries().size(); i++) {
Entry entry = (Entry)f.getEntries().get(i);
AppModule entryAppModule = (AppModule)entry.getModule(AppModule.URI);
AppModule eAppModule = (AppModule)entry.getModule(AppModule.URI);
if (eAppModule.getEdited().before(entryAppModule.getEdited())) {
f.getEntries().add(i, e);
inserted = true;
break;
}
}
if (!inserted) {
f.getEntries().add(0, e);
}
updateFeedDocument(f);
}
private Entry findEntry(String id, Feed f) {
List l = f.getEntries();
for (Iterator it = l.iterator(); it.hasNext();) {
Entry e = (Entry)it.next();
if (id.equals(e.getId()))
return e;
}
return null;
}
private void updateFeedDocument(Feed f) throws AtomException{
try {
synchronized(FileStore.getFileStore()) {
WireFeedOutput wireFeedOutput = new WireFeedOutput();
Document feedDoc = wireFeedOutput.outputJDom( f );
XMLOutputter outputter = new XMLOutputter();
//outputter.setFormat(Format.getPrettyFormat());
OutputStream fos = FileStore.getFileStore().getFileOutputStream(getFeedPath());
outputter.output(feedDoc, new OutputStreamWriter(fos, "UTF-8"));
}
} catch (FeedException fex) {
throw new AtomException(fex);
}catch (IOException ex) {
throw new AtomException(ex);
}
}
private InputStream createDefaultFeedDocument(String uri) throws AtomException {
Feed f = new Feed();
f.setTitle("Feed");
f.setId(uri);
f.setFeedType( FEED_TYPE);
Link selfLink = new Link();
selfLink.setRel("self");
selfLink.setHref(uri);
f.getOtherLinks().add(selfLink);
try {
WireFeedOutput wireFeedOutput = new WireFeedOutput();
Document feedDoc = wireFeedOutput.outputJDom( f );
XMLOutputter outputter = new XMLOutputter();
//outputter.setFormat(Format.getCompactFormat());
OutputStream fos = FileStore.getFileStore().getFileOutputStream(getFeedPath());
outputter.output(feedDoc, new OutputStreamWriter(fos, "UTF-8"));
} catch (FeedException ex) {
throw new AtomException(ex);
} catch (IOException ex) {
throw new AtomException(ex);
} catch ( Exception e ) {
e.printStackTrace();
}
return FileStore.getFileStore().getFileInputStream(getFeedPath());
}
private Entry loadAtomResourceEntry(InputStream in, File file) {
try {
Entry entry = Atom10Parser.parseEntry(
new BufferedReader(new InputStreamReader(in)), null);
updateMediaEntryAppLinks(entry, file.getName(), true);
return entry;
} catch ( Exception e ) {
e.printStackTrace();
return null;
}
}
private void updateEntryAppLinks(Entry entry, String fsid, boolean singleEntry) {
entry.setId("urn:uuid:" + fsid);
// Look for existing alt links and the alt link
Link altLink = null;
List altLinks = entry.getAlternateLinks();
if (altLinks != null) {
for (Iterator it = altLinks.iterator(); it.hasNext();) {
Link link = (Link)it.next();
if (link.getRel() == null || "alternate".equals(link.getRel())) {
altLink = link;
break;
}
}
} else {
// No alt links found, so add them now
altLinks = new ArrayList();
entry.setAlternateLinks(altLinks);
}
// The alt link not found, so add it now
if (altLink == null) {
altLink = new Link();
altLinks.add(altLink);
}
// Set correct value for the alt link
altLink.setRel("alternate");
altLink.setHref(getEntryViewURI(fsid));
// Look for existing other links and the edit link
Link editLink = null;
List otherLinks = entry.getOtherLinks();
if (otherLinks != null) {
for (Iterator it = otherLinks.iterator(); it.hasNext();) {
Link link = (Link)it.next();
if ("edit".equals(link.getRel())) {
editLink = link;
break;
}
}
} else {
// No other links found, so add them now
otherLinks = new ArrayList();
entry.setOtherLinks(otherLinks);
}
// The edit link not found, so add it now
if (editLink == null) {
editLink = new Link();
otherLinks.add(editLink);
}
// Set correct value for the edit link
editLink.setRel("edit");
editLink.setHref(getEntryEditURI(fsid, relativeURIs, singleEntry));
}
private void updateMediaEntryAppLinks(Entry entry, String fileName, boolean singleEntry) {
// TODO: figure out why PNG is missing from Java MIME types
FileTypeMap map = FileTypeMap.getDefaultFileTypeMap();
if (map instanceof MimetypesFileTypeMap) {
try {
((MimetypesFileTypeMap)map).addMimeTypes("image/png png PNG");
} catch (Exception ignored) {}
}
String contentType = map.getContentType(fileName);
entry.setId(getEntryMediaViewURI(fileName));
entry.setTitle(fileName);
entry.setUpdated(new Date());
List otherlinks = new ArrayList();
entry.setOtherLinks(otherlinks);
Link editlink = new Link();
editlink.setRel("edit");
editlink.setHref(getEntryEditURI(fileName, relativeURIs, singleEntry));
otherlinks.add(editlink);
Link editMedialink = new Link();
editMedialink.setRel("edit-media");
editMedialink.setHref(getEntryMediaEditURI(fileName, relativeURIs, singleEntry));
otherlinks.add(editMedialink);
Content content = (Content)entry.getContents().get(0);
content.setSrc(getEntryMediaViewURI(fileName));
List contents = new ArrayList();
contents.add(content);
entry.setContents(contents);
}
/**
* Create a Rome Atom entry based on a Roller entry.
* Content is escaped.
* Link is stored as rel=alternate link.
*/
private Entry loadAtomEntry(InputStream in) {
try {
return Atom10Parser.parseEntry(
new BufferedReader(new InputStreamReader(in, "UTF-8")), null);
} catch ( Exception e ) {
e.printStackTrace();
return null;
}
}
/**
* Update existing or add new app:edited.
*/
private void updateTimestamps(Entry entry) {
// We're not differenting between an update and an edit (yet)
entry.setUpdated(new Date());
AppModule appModule = (AppModule)entry.getModule(AppModule.URI);
if (appModule == null) {
appModule = new AppModuleImpl();
List modules = entry.getModules()==null ? new ArrayList() : entry.getModules();
modules.add(appModule);
entry.setModules(modules);
}
appModule.setEdited(entry.getUpdated());
}
/**
* Save file to website's resource directory.
* @param handle Weblog handle to save to
* @param name Name of file to save
* @param size Size of file to be saved
* @param is Read file from input stream
*/
private void saveMediaFile(
String name, String contentType, long size, InputStream is) throws AtomException {
byte[] buffer = new byte[8192];
int bytesRead = 0;
File dirPath = new File(getEntryMediaPath(name));
if (!dirPath.getParentFile().exists()) {
dirPath.getParentFile().mkdirs();
}
OutputStream bos = null;
try {
bos = new FileOutputStream(dirPath.getAbsolutePath());
while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
bos.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
throw new AtomException("ERROR uploading file", e);
} finally {
try {
bos.flush();
bos.close();
} catch (Exception ignored) {}
}
}
/**
* Creates a file name for a file based on a weblog handle, title string and a
* content-type.
*
* @param handle Weblog handle
* @param title Title to be used as basis for file name (or null)
* @param contentType Content type of file (must not be null)
*
* If a title is specified, the method will apply the same create-anchor
* logic we use for weblog entries to create a file name based on the title.
*
* If title is null, the base file name will be the weblog handle plus a
* YYYYMMDDHHSS timestamp.
*
* The extension will be formed by using the part of content type that
* comes after he slash.
*
* For example:
* weblog.handle = "daveblog"
* title = "Port Antonio"
* content-type = "image/jpg"
* Would result in port_antonio.jpg
*
* Another example:
* weblog.handle = "daveblog"
* title = null
* content-type = "image/jpg"
* Might result in daveblog-200608201034.jpg
*/
private String createFileName(String title, String contentType) {
if (handle == null) throw new IllegalArgumentException("weblog handle cannot be null");
if (contentType == null) throw new IllegalArgumentException("contentType cannot be null");
String fileName = null;
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern("yyyyMMddHHssSSS");
// Determine the extension based on the contentType. This is a hack.
// The info we need to map from contentType to file extension is in
// JRE/lib/content-type.properties, but Java Activation doesn't provide
// a way to do a reverse mapping or to get at the data.
String[] typeTokens = contentType.split("/");
String ext = typeTokens[1];
if (title != null && !title.trim().equals("")) {
// We've got a title, so use it to build file name
String base = Utilities.replaceNonAlphanumeric(title, ' ');
StringTokenizer toker = new StringTokenizer(base);
String tmp = null;
int count = 0;
while (toker.hasMoreTokens() && count < 5) {
String s = toker.nextToken();
s = s.toLowerCase();
tmp = (tmp == null) ? s : tmp + "_" + s;
count++;
}
fileName = tmp + "-" + sdf.format(new Date()) + "." + ext;
} else {
// No title or text, so instead we'll use the item's date
// in YYYYMMDD format to form the file name
fileName = handle + "-" + sdf.format(new Date()) + "." + ext;
}
return fileName;
}
//------------------------------------------------------------ URI methods
private String getEntryEditURI(String fsid, boolean relative, boolean singleEntry) {
String entryURI = null;
if (relative) {
if (singleEntry) {
entryURI = fsid;
} else {
entryURI = singular + "/" + fsid;
}
} else {
entryURI = contextURI + servletPath + "/" + handle + "/" + singular + "/" + fsid;
}
return entryURI;
}
private String getEntryViewURI(String fsid) {
return contextURI + "/" + handle + "/" + collection + "/" + fsid + "/entry.xml";
}
private String getEntryMediaEditURI(String fsid, boolean relative, boolean singleEntry) {
String entryURI = null;
if (relative) {
if (singleEntry) {
entryURI = "media/" + fsid;
} else {
entryURI = singular + "/media/" + fsid;
}
} else {
entryURI = contextURI + servletPath + "/" + handle + "/" + singular + "/media/" + fsid;
}
return entryURI;
}
private String getEntryMediaViewURI(String fsid) {
return contextURI + "/" + handle + "/" + collection + "/" + fsid + "/media/" + fsid;
}
private String getCategoriesURI() {
if (relativeURIs) {
return contextURI + servletPath + "/" + handle + "/" + singular + "/categories";
} else {
return servletPath + "/" + handle + "/" + singular + "/categories";
}
}
//------------------------------------------------------- File path methods
private String getBaseDir() {
return baseDir;
}
private String getFeedPath() {
return getBaseDir() + handle
+ File.separator + collection + File.separator+ "feed.xml";
}
private String getEntryDirPath(String id) {
return getBaseDir() + handle
+ File.separator + collection + File.separator + id;
}
private String getEntryPath(String id) {
return getEntryDirPath(id) + File.separator + "entry.xml";
}
private String getEntryMediaPath(String id) {
return getEntryDirPath(id) + File.separator + "media" + File.separator + id;
}
private static void checkExistence(String path) throws AtomNotFoundException{
if (!FileStore.getFileStore().exists(path)) {
throw new AtomNotFoundException("Entry does not exist");
}
}
}

View file

@ -1,34 +0,0 @@
/*
* 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 com.sun.syndication.propono.atom.common.Workspace;
/**
* File based Atom service Workspace.
*/
public class FileBasedWorkspace extends Workspace {
private String baseDir = null;
private String handle = null;
/** Creates a new instance of FileBasedWorkspace */
public FileBasedWorkspace(String handle, String baseDir) {
super(handle, "text");
this.handle = handle;
this.baseDir = baseDir;
}
}

View file

@ -1,116 +0,0 @@
/*
* 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.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Class which helps in handling File persistence related operations.
*/
class FileStore {
private static Log log =
LogFactory.getFactory().getInstance(FileStore.class);
private static final FileStore fileStore = new FileStore();
public String getNextId() {
//return UUID.randomUUID().toString(); // requires JDK 1.5
return RandomStringUtils.randomAlphanumeric(20);
}
public boolean exists(String path) {
File f = new File(path);
return f.exists();
}
public InputStream getFileInputStream(String path) {
log.debug("getFileContents path: " + path);
try {
return new BufferedInputStream(new FileInputStream(path));
} catch (FileNotFoundException e) {
log.debug(" File not found: " + path);
return null;
}
}
public OutputStream getFileOutputStream(String path) {
log.debug("getFileOutputStream path: " + path);
try {
File f = new File(path);
f.getParentFile().mkdirs();
return new BufferedOutputStream(new FileOutputStream(f));
} catch (FileNotFoundException e) {
log.debug(" File not found: " + path);
return null;
}
}
public void createOrUpdateFile(String path, InputStream content) throws FileNotFoundException, IOException {
log.debug("createOrUpdateFile path: " + path);
File f = new File(path);
f.mkdirs();
FileOutputStream out = new FileOutputStream(f);
byte[] buffer = new byte[2048];
int read;
while ((read = content.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
public void deleteFile(String path) {
log.debug("deleteFile path: " + path);
File f = new File(path);
if (!f.delete()) {
log.debug(" Failed to delete: " + f.getAbsolutePath());
}
}
public static FileStore getFileStore() {
return fileStore;
}
public boolean deleteDirectory(String path) {
return deleteDirectory(new File(path));
}
public boolean deleteDirectory(File path) {
log.debug("deleteDirectory path: " + path);
if( path.exists() ) {
File[] files = path.listFiles();
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
} else {
files[i].delete();
}
}
}
return( path.delete() );
}
}

View file

@ -1,193 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Base implementation of a blog entry.
*/
public abstract class BaseBlogEntry implements BlogEntry {
protected String id = null;
protected Person author = null;
protected Content content = null;
protected String title = null;
protected String permalink = null;
protected String summary = null;
protected Date modificationDate = null;
protected Date publicationDate = null;
protected List categories = new ArrayList();
protected boolean draft = false;
private Blog blog = null;
/**
* Contruct abstract blog entry.
*/
public BaseBlogEntry(Blog blog) {
this.blog = blog;
}
/**
* {@inheritDoc}
*/
public String getId() {
return id;
}
/**
* {@inheritDoc}
*/
public String getPermalink() {
return permalink;
}
void setPermalink(String permalink) {
this.permalink = permalink;
}
/**
* {@inheritDoc}
*/
public Person getAuthor() {
return author;
}
/**
* {@inheritDoc}
*/
public void setAuthor(Person author) {
this.author = author;
}
/**
* {@inheritDoc}
*/
public Content getContent() {
return content;
}
/**
* {@inheritDoc}
*/
public void setContent(Content content) {
this.content = content;
}
/**
* {@inheritDoc}
*/
public boolean getDraft() {
return draft;
}
/**
* {@inheritDoc}
*/
public void setDraft(boolean draft) {
this.draft = draft;
}
/**
* {@inheritDoc}
*/
public Date getPublicationDate() {
return publicationDate;
}
/**
* {@inheritDoc}
*/
public void setPublicationDate(Date pubDate) {
this.publicationDate = pubDate;
}
/**
* {@inheritDoc}
*/
public Date getModificationDate() {
return modificationDate;
}
/**
* {@inheritDoc}
*/
public void setModificationDate(Date date) {
modificationDate = date;
}
/**
* {@inheritDoc}
*/
public String getTitle() {
return title;
}
/**
* {@inheritDoc}
*/
public void setTitle(String title) {
this.title = title;
}
/**
* {@inheritDoc}
*/
public String getSummary() {
return summary;
}
/**
* {@inheritDoc}
*/
public void setSummary(String summary) {
this.summary = summary;
}
/**
* {@inheritDoc}
*/
public List getCategories() {
return categories;
}
/**
* {@inheritDoc}
*/
public void setCategories(List categories) {
this.categories = categories;
}
/**
* {@inheritDoc}
*/
public Blog getBlog() {
return blog;
}
void setBlog(Blog blog) {
this.blog = blog;
}
/**
* String representation, returns id.
*/
public String toString() {
return id;
}
}

View file

@ -1,213 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient;
import java.util.List;
import java.util.Iterator;
/**
* <p>Represents a blog, which has collections of entries and resources.
* You can access the collections using the getCollections() and
* getCollection(String name) methods, which return Blog.Collection objects,
* which you can use to create, retrieve update or delete entries within
* a collection.</p>
*/
public interface Blog {
/**
* Token can be used to fetch this blog again from getBlog() method.
* @return Blog object specified by token.
*/
public String getToken();
/**
* Name of this blog.
* @return Display name of this blog.
*/
public String getName();
/**
* Get a single BlogEntry (or BlogResource) by token.
* @param token Token from blog entry's getToken() method.
* @throws com.sun.syndication.propono.blogclient.BlogClientException On error fetching the blog entry.
* @return Blog entry specified by token.
*/
public BlogEntry getEntry(String token) throws BlogClientException;
/**
* Gets listing of entry and resource collections available in the blog,
* including the primary collections.
* @throws BlogClientException On error fetching collections.
* @return List of Blog.Collection objects.
*/
public List getCollections() throws BlogClientException;
/**
* Get collection by token.
* @param token Token from a collection's getToken() method.
* @throws BlogClientException On error fetching collection.
* @return Blog.Collection object.
*/
public Collection getCollection(String token) throws BlogClientException;
/**
* Represents an entry or resource collection on a blog server.
*/
public interface Collection {
/**
* Get blog that contains this collection.
* @return Blog that contains this collection.
*/
public Blog getBlog();
/**
* Title of collection.
* @return Title of collecton.
*/
public String getTitle();
/**
* Token that can be used to fetch collection.
* @return Token that can be used to fetch collection.
*/
public String getToken();
/**
* Content-types accepted by collection.
* @return Comma-separated list of content-types accepted.
*/
public List getAccepts();
/**
* Determines if collection will accept a content-type.
* @param contentType Content-type to be considered.
* @return True of content type will be accepted, false otherwise.
*/
public boolean accepts(String contentType);
/**
* Return categories allowed by colletion.
* @throws BlogClientException On error fetching categories.
* @return List of BlogEntry.Category objects for this collection.
*/
public List getCategories() throws BlogClientException;
/**
* Create but do not save new entry in collection.
* To save entry, call its save() method.
* @throws BlogClientException On error creating entry.
* @return New BlogEntry object.
*/
public BlogEntry newEntry() throws BlogClientException;
/**
* Create but do not save new resource in collection.
* To save resource, call its save() method.
* @param name Name of new resource.
* @param contentType MIME content-type of new resource.
* @param bytes Data for new resource.
* @throws BlogClientException On error creating entry.
* @return New BlogResource object,
*/
public BlogResource newResource(String name, String contentType, byte[] bytes) throws BlogClientException;
/**
* Get iterator over entries/resources in this collection.
* @return List of BlogEntry objects, some may be BlogResources.
* @throws BlogClientException On error fetching entries/resources.
*/
public Iterator getEntries() throws BlogClientException;
/**
* Save or update a BlogEntry in this collection by adding it to this
* collection and then calling it's entry.save() method.
* @param entry BlogEntry to be saved.
* @throws BlogClientException On error saving entry.
* @return URI of entry.
*/
public String saveEntry(BlogEntry entry) throws BlogClientException;
/**
* Save or update resource in this collection
* @param resource BlogResource to be saved.
* @throws BlogClientException On error saving resource.
* @return URI of resource.
*/
public String saveResource(BlogResource resource) throws BlogClientException;
}
// Deprecated primary collection methods, instead use collections directly.
/**
* Get iterator over entries in primary entries collection (the first
* collection that accepts entries). Note that entries may be partial,
* so don't try to update and save them: to update and entry, first fetch
* it with getEntry(), change fields, then call entry.save();
* @return To iterate over all entries in collection.
* @throws BlogClientException On failure or if there is no primary entries collection.
*
* @deprecated Instead use collections directly.
*/
public Iterator getEntries() throws BlogClientException;
/**
* Get entries in primary resources collection (the first
* collection that accepts anything other than entries).
* @throws BlogClientException On failure or if there is no primary resources collection.
* @return To iterate over all resojrces in collection.
*
* @deprecated Instead use collections directly.
*/
public Iterator getResources() throws BlogClientException;
/**
* Create but do not save it to server new BlogEntry in primary entries collection
* (the first collection found that accepts entries). To save the entry to the
* server to a collection, use the entry's save() method.
* @throws BlogClientException On error or if there is no primary entries collection.
* @return Unsaved BlogEntry in primary entries collection.
*
* @deprecated Instead use collections directly.
*/
public BlogEntry newEntry() throws BlogClientException;
/**
* Create but do not save it to server new BlogResource in primary resources collection
* (the first collection found that accepts resources). To save the resource to the
* server to a collection, use the resource's save() method.
* @param name Name of resource to be saved.
* @param type MIME content type of resource data.
* @param bytes Bytes of resource data.
* @throws BlogClientException On error or if there is no primary respurces collection.
* @return Unsaved BlogEntry in primary resources collection.
*
* @deprecated Instead use collections directly.
*/
public BlogResource newResource(String name, String type, byte[] bytes)
throws BlogClientException;
/**
* Returns list of available BlogEntry.Category in primary entries collection.
* @throws BlogClientException On error or if there is no primary entries collection.
* @return List of BlogEntry.Category objects.
*
* @deprecated Instead use collections directly.
*/
public List getCategories() throws BlogClientException;
}

View file

@ -1,40 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient;
/**
* Represents a Blog Client exception, the library throws these instead of
* implementation specific exceptions.
*/
public class BlogClientException extends Exception {
/**
* Construct a new exception
* @param msg Text message that explains exception
*/
public BlogClientException(String msg) {
super(msg);
}
/**
* Construct a new exception which wraps a throwable.
* @param msg Text message that explains exception
* @param t Throwable to be wrapped by exception
*/
public BlogClientException(String msg, Throwable t) {
super(msg, t);
}
}

View file

@ -1,34 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient;
import java.util.List;
/**
* A BlogConnection is a single-user connection to a blog server where the user
* has access to multiple blogs, which are each represented by a Blog interface.
*/
public interface BlogConnection {
/** Returns collection of blogs available from this connection */
public abstract List getBlogs();
/** Get blog by token */
public abstract Blog getBlog(String token);
/** Set appkey (optional, needed by some blog servers) */
public void setAppkey(String appkey);
}

View file

@ -1,80 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient;
import java.lang.reflect.Constructor;
/**
* Entry point to the Blogapps blog client library.
*/
public class BlogConnectionFactory {
// BlogConnection implementations must:
// 1) implement BlogConnection
// 2) privide contructor that accepts three strings args: url, username and password.
// TODO: make implementations configurable
private static String ATOMPROTOCOL_IMPL_CLASS =
"com.sun.syndication.propono.blogclient.atomprotocol.AtomConnection";
private static String METAWEBLOG_IMPL_CLASS =
"com.sun.syndication.propono.blogclient.metaweblog.MetaWeblogConnection";
/**
* Create a connection to a blog server.
* @param type Connection type, must be "atom" or "metaweblog"
* @param url End-point URL to connect to
* @param username Username for login to blog server
* @param password Password for login to blog server
*/
public static BlogConnection getBlogConnection(
String type, String url, String username, String password)
throws BlogClientException {
BlogConnection blogConnection = null;
if (type == null || type.equals("metaweblog")) {
blogConnection = createBlogConnection(
METAWEBLOG_IMPL_CLASS, url, username, password);
} else if (type.equals("atom")) {
blogConnection = createBlogConnection(
ATOMPROTOCOL_IMPL_CLASS, url, username, password);
} else {
throw new BlogClientException("Type must be 'atom' or 'metaweblog'");
}
return blogConnection;
}
private static BlogConnection createBlogConnection(
String className, String url, String username, String password)
throws BlogClientException {
Class conClass;
try {
conClass = Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new BlogClientException(
"BlogConnection impl. class not found: "+className, ex);
}
Class[] args = new Class[] {String.class, String.class, String.class};
Constructor ctor;
try {
ctor = conClass.getConstructor(args);
return (BlogConnection)
ctor.newInstance(new Object[] {url, username, password});
} catch (Throwable t) {
throw new BlogClientException(
"ERROR instantiating BlogConnection impl.", t);
}
}
}

View file

@ -1,231 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient;
import java.util.Date;
import java.util.List;
import java.io.InputStream;
/**
* Represents a single blog entry.
*/
public interface BlogEntry {
/** Get token, which can be used to fetch the blog entry */
public String getToken();
/**
* Save this entry to it's collection. If this is a new entry and does not
* have a collection yet, then save() will save it to the primary collection.
*/
public void save() throws BlogClientException;
/** Delete this entry from blog server */
public void delete() throws BlogClientException;
/** Permanent link to this entry (assigned by server) */
public String getPermalink();
/** Blog is associated with a blog */
public Blog getBlog();
/** Get categories, a list of BlogEntry.Category objects */
public List getCategories();
/** Set categories, a list of BlogEntry.Category objects */
public void setCategories(List categories);
/** Get globally unique ID of this blog entry */
public String getId();
/** Get title of this blog entry */
public String getTitle();
/** Set title of this blog entry */
public void setTitle(String title);
/** Get summary of this blog entry */
public String getSummary();
/** Set summary of this blog entry */
public void setSummary(String summary);
/** Get content of this blog entry */
public Content getContent();
/** Set content of this blog entry */
public void setContent(Content content);
/** Get draft status of this entry */
public boolean getDraft();
/** Set draft status of this entry */
public void setDraft(boolean draft);
/** Get author of this entry */
public Person getAuthor();
/** Set author of this entry */
public void setAuthor(Person author);
/** Set publish date of this entry */
public Date getPublicationDate();
/** Get publish date of this entry */
public void setPublicationDate(Date date);
/** Get update date of this entry */
public Date getModificationDate();
/** Set update date of this entry */
public void setModificationDate(Date date);
/** Represents blog entry content */
public class Content {
String type = "html";
String value = null;
String src = null;
/** Construct content */
public Content() {}
/** Construct content with value (and type="html") */
public Content(String value) {
this.value = value;
}
/** Get value of content if in-line */
public String getValue() {
return value;
}
/** Set value of content if in-line */
public void setValue(String value) {
this.value = value;
}
/**
* Get type of content, either "text", "html", "xhtml" or a MIME content-type.
* Defaults to HTML.
*/
public String getType() {
return type;
}
/**
* Set type of content, either "text", "html", "xhtml" or a MIME content-type.
* Defaults to HTML.
*/
public void setType(String type) {
this.type = type;
}
/** Get URI of content if out-of-line */
public String getSrc() {
return src;
}
/** Set URI of content if out-of-line */
public void setSrc(String src) {
this.src = src;
}
}
/** Represents a blog author or contributor */
public class Person {
String name;
String email;
String url;
/** Get person's email */
public String getEmail() {
return email;
}
/** Set person's email */
public void setEmail(String email) {
this.email = email;
}
/** Get person's name */
public String getName() {
return name;
}
/** Set person's name */
public void setName(String name) {
this.name = name;
}
/** Get person's URL */
public String getUrl() {
return url;
}
/** Set person's URL */
public void setUrl(String url) {
this.url = url;
}
/** Returns person's name */
public String toString() {
return name;
}
}
/** Represents a weblog category */
public class Category {
String id;
String name;
String url;
/**
* Create new Catetory
*/
public Category() {}
/**
* Create new category with name.
*/
public Category(String id) {
this.id = id;
this.name = id;
}
/**
* Determines if categories are equal based on id.
*/
public boolean equals(Object obj) {
Category other = (Category)obj;
if (obj == null) return false;
if (getId() != null && other.getId() != null
&& getId().equals(other.getId())) return true;
return false;
}
/** Get category id */
public String getId() {
return id;
}
/** Set category id */
public void setId(String id) {
this.id = id;
}
/** Get category display name */
public String getName() {
return name;
}
/** Set category display name */
public void setName(String name) {
this.name = name;
}
/** Get URL of category domain */
public String getUrl() {
return url;
}
/** Set URL of category domain */
public void setUrl(String url) {
this.url = url;
}
/** Return category's name or id for display */
public String toString() {
return name!=null ? name : id;
}
}
}

View file

@ -1,39 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient;
import java.io.InputStream;
/**
* Represents a file that has been uploaded to a blog.
* <p />
* Resources are modeled as a type of BlogEntry, but be aware: not all servers
* can save resource metadata (i.e. title, category, author, etc.). MetaWeblog
* based servers can't save metadata at all and Atom protocol servers are not
* required to preserve uploaded file metadata.
*/
public interface BlogResource extends BlogEntry {
/** Get resource name (name is required) */
public String getName();
/** Get resource as stream, using content.src as URL */
public InputStream getAsStream() throws BlogClientException;
/** Update resource by immediately uploading new bytes to server */
public void update(byte[] newBytes) throws BlogClientException;
}

View file

@ -1,206 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.atomprotocol;
import com.sun.syndication.propono.utils.ProponoException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sun.syndication.propono.blogclient.Blog;
import com.sun.syndication.propono.blogclient.BlogClientException;
import com.sun.syndication.propono.blogclient.BlogEntry;
import com.sun.syndication.propono.blogclient.BlogResource;
import com.sun.syndication.propono.atom.client.ClientAtomService;
import com.sun.syndication.propono.atom.client.ClientCollection;
import com.sun.syndication.propono.atom.client.ClientEntry;
import com.sun.syndication.propono.atom.client.ClientMediaEntry;
import com.sun.syndication.propono.atom.client.ClientWorkspace;
import java.util.Map;
import java.util.TreeMap;
/**
* Atom protocol implementation of the BlogClient Blog interface.
*/
public class AtomBlog implements Blog {
static final Log logger = LogFactory.getLog(AtomBlog.class);
private HttpClient httpClient = null;
private String name = null;
private ClientAtomService service;
private ClientWorkspace workspace = null;
private AtomCollection entriesCollection = null;
private AtomCollection resourcesCollection = null;
private Map collections = new TreeMap();
/**
* Create AtomBlog using specified HTTPClient, user account and workspace,
* called by AtomConnection. Fetches Atom Service document and creates
* an AtomCollection object for each collection found. The first entry
* collection is considered the primary entry collection. And the first
* resource collection is considered the primary resource collection.
*/
AtomBlog(ClientAtomService service, ClientWorkspace workspace) {
this.setService(service);
this.setWorkspace(workspace);
this.name = workspace.getTitle();
Iterator members = workspace.getCollections().iterator();
while (members.hasNext()) {
ClientCollection col = (ClientCollection) members.next();
if (col.accepts("entry") && entriesCollection == null) {
// first entry collection is primary entry collection
entriesCollection = new AtomCollection(this, col);
}
else if (!col.accepts("entry") && resourcesCollection == null) {
// first non-entry collection is primary resource collection
resourcesCollection = new AtomCollection(this, col);
}
collections.put(col.getHrefResolved(), new AtomCollection(this, col));
}
}
/**
* {@inheritDoc}
*/
public String getName() { return name; }
/**
* String display of blog, returns name.
*/
public String toString() { return getName(); }
/**
* {@inheritDoc}
*/
public String getToken() { return entriesCollection.getToken(); }
/**
* {@inheritDoc}
*/
public BlogEntry newEntry() throws BlogClientException {
if (entriesCollection == null) throw new BlogClientException("No entry collection");
return entriesCollection.newEntry();
}
/**
* {@inheritDoc}
*/
public BlogEntry getEntry(String token) throws BlogClientException {
ClientEntry clientEntry = null;
AtomEntry atomEntry = null;
try {
clientEntry = getService().getEntry(token);
} catch (ProponoException ex) {
throw new BlogClientException("ERROR: fetching entry", ex);
}
if (clientEntry != null && clientEntry instanceof ClientMediaEntry) {
return new AtomResource(this, (ClientMediaEntry)clientEntry);
} else if (clientEntry != null && clientEntry instanceof ClientEntry) {
return new AtomEntry(this, clientEntry);
} else {
throw new BlogClientException("ERROR: unknown object type returned");
}
}
/**
* {@inheritDoc}
*/
public Iterator getEntries() throws BlogClientException {
if (entriesCollection == null) throw new BlogClientException("No primary entry collection");
return new AtomEntryIterator(entriesCollection);
}
/**
* {@inheritDoc}
*/
public Iterator getResources() throws BlogClientException {
if (resourcesCollection == null) throw new BlogClientException("No primary entry collection");
return new AtomEntryIterator(resourcesCollection);
}
String saveEntry(BlogEntry entry) throws BlogClientException {
if (entriesCollection == null) throw new BlogClientException("No primary entry collection");
return entriesCollection.saveEntry(entry);
}
void deleteEntry(BlogEntry entry) throws BlogClientException {
if (entriesCollection == null) throw new BlogClientException("No primary entry collection");
entriesCollection.deleteEntry(entry);
}
/**
* {@inheritDoc}
*/
public List getCategories() throws BlogClientException {
if (entriesCollection == null) throw new BlogClientException("No primary entry collection");
return entriesCollection.getCategories();
}
/**
* {@inheritDoc}
*/
public BlogResource newResource(
String name, String contentType, byte[] bytes) throws BlogClientException {
if (resourcesCollection == null) {
throw new BlogClientException("No resource collection");
}
return resourcesCollection.newResource(name, contentType, bytes);
}
String saveResource(BlogResource res) throws BlogClientException {
if (resourcesCollection == null) throw new BlogClientException("No primary resource collection");
return resourcesCollection.saveResource(res);
}
void deleteResource(BlogResource resource) throws BlogClientException {
deleteEntry((BlogEntry)resource);
}
/**
* {@inheritDoc}
*/
public List getCollections() throws BlogClientException {
return new ArrayList(collections.values());
}
/**
* {@inheritDoc}
*/
public Blog.Collection getCollection(String token) throws BlogClientException {
return (Blog.Collection)collections.get(token);
}
ClientAtomService getService() {
return service;
}
void setService(ClientAtomService service) {
this.service = service;
}
ClientWorkspace getWorkspace() {
return workspace;
}
void setWorkspace(ClientWorkspace workspace) {
this.workspace = workspace;
}
}

View file

@ -1,165 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.atomprotocol;
import com.sun.syndication.feed.atom.Category;
import com.sun.syndication.propono.atom.client.ClientAtomService;
import com.sun.syndication.propono.atom.common.Categories;
import com.sun.syndication.propono.atom.client.ClientCollection;
import com.sun.syndication.propono.atom.client.ClientEntry;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sun.syndication.propono.blogclient.Blog;
import com.sun.syndication.propono.blogclient.BlogClientException;
import com.sun.syndication.propono.blogclient.BlogEntry;
import com.sun.syndication.propono.blogclient.BlogResource;
/**
* Atom protocol implementation of BlogClient Blog.Collection.
*/
public class AtomCollection implements Blog.Collection {
static final Log logger = LogFactory.getLog(AtomCollection.class);
private Blog blog = null;
private List categories = new ArrayList();
private ClientCollection clientCollection = null;
AtomCollection(AtomBlog blog, ClientCollection col) {
this.blog = blog;
this.clientCollection = col;
for (Iterator catsIter = col.getCategories().iterator(); catsIter.hasNext();) {
Categories cats = (Categories)catsIter.next();
for (Iterator catIter = cats.getCategories().iterator(); catIter.hasNext();) {
Category cat = (Category)catIter.next();
BlogEntry.Category blogCat = new BlogEntry.Category(cat.getTerm());
blogCat.setName(cat.getLabel());
blogCat.setUrl(cat.getScheme());
getCategories().add(blogCat);
}
}
}
/**
* {@inheritDoc}
*/
public String getTitle() {
return getClientCollection().getTitle();
}
/**
* {@inheritDoc}
*/
public String getToken() {
return getClientCollection().getHrefResolved();
}
/**
* {@inheritDoc}
*/
public List getAccepts() {
return getClientCollection().getAccepts();
}
/**
* {@inheritDoc}
*/
public boolean accepts(String ct) {
return getClientCollection().accepts(ct);
}
/**
* {@inheritDoc}
*/
public Iterator getEntries() throws BlogClientException {
return new AtomEntryIterator(this);
}
/**
* {@inheritDoc}
*/
public BlogEntry newEntry() throws BlogClientException {
AtomBlog atomBlog = (AtomBlog)getBlog();
BlogEntry entry = new AtomEntry(atomBlog, this);
return entry;
}
/**
* {@inheritDoc}
*/
public BlogResource newResource(String name, String contentType, byte[] bytes) throws BlogClientException {
return new AtomResource(this, name, contentType, bytes);
}
/**
* {@inheritDoc}
*/
public String saveResource(BlogResource res) throws BlogClientException {
((AtomResource)res).setCollection(this);
res.save();
return res.getContent().getSrc();
}
/**
* {@inheritDoc}
*/
public String saveEntry(BlogEntry entry) throws BlogClientException {
((AtomEntry)entry).setCollection(this);
entry.save();
return entry.getPermalink();
}
void deleteEntry(BlogEntry entry) throws BlogClientException {
try {
ClientAtomService service = ((AtomBlog)getBlog()).getService();
ClientEntry clientEntry = service.getEntry(entry.getToken());
clientEntry.remove();
} catch (Exception e) {
throw new BlogClientException("ERROR deleting entry", e);
}
}
/**
* {@inheritDoc}
*/
public Blog getBlog() {
return blog;
}
void setBlog(AtomBlog blog) {
this.blog = blog;
}
/**
* {@inheritDoc}
*/
public List getCategories() {
return categories;
}
void setCategories(List categories) {
this.categories = categories;
}
ClientCollection getClientCollection() {
return clientCollection;
}
}

View file

@ -1,92 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.atomprotocol;
import com.sun.syndication.propono.atom.client.AtomClientFactory;
import com.sun.syndication.propono.atom.client.BasicAuthStrategy;
import com.sun.syndication.propono.atom.client.ClientAtomService;
import com.sun.syndication.propono.atom.client.ClientWorkspace;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import com.sun.syndication.propono.blogclient.BlogConnection;
import com.sun.syndication.propono.blogclient.Blog;
import com.sun.syndication.propono.blogclient.BlogClientException;
/**
* Atom protocol of BlogConnection. Connects to Atom server, creates AtomBlog
* object for each Atom workspace found and within each blog a collection for each
* Atom collection found.
*/
public class AtomConnection implements BlogConnection {
private static Log logger = LogFactory.getLog(AtomConnection.class);
private HttpClient httpClient = null;
private Map blogs = new HashMap();
/**
* Create Atom blog client instance for specified URL and user account.
* @param uri End-point URL of Atom service
* @param username Username of account
* @param password Password of account
*/
public AtomConnection(String uri, String username, String password)
throws BlogClientException {
Document doc = null;
try {
ClientAtomService service = (ClientAtomService)
AtomClientFactory.getAtomService(uri, new BasicAuthStrategy(username, password));
Iterator iter = service.getWorkspaces().iterator();
int count = 0;
while (iter.hasNext()) {
ClientWorkspace workspace = (ClientWorkspace)iter.next();
Blog blog = new AtomBlog(service, workspace);
blogs.put(blog.getToken(), blog);
}
} catch (Throwable t) {
throw new BlogClientException("Error connecting to blog server", t);
}
}
/**
* {@inheritDoc}
*/
public List getBlogs() {
return new ArrayList(blogs.values());
}
/**
* {@inheritDoc}
*/
public Blog getBlog(String token) {
return (AtomBlog)blogs.get(token);
}
/**
* {@inheritDoc}
*/
public void setAppkey(String appkey) {
}
}

View file

@ -1,240 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.atomprotocol;
import com.sun.syndication.propono.utils.ProponoException;
import com.sun.syndication.propono.atom.common.rome.AppModule;
import com.sun.syndication.propono.atom.common.rome.AppModuleImpl;
import com.sun.syndication.propono.blogclient.BlogClientException;
import com.sun.syndication.propono.blogclient.BlogEntry;
import com.sun.syndication.propono.blogclient.BaseBlogEntry;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.propono.atom.client.ClientEntry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sun.syndication.propono.blogclient.BlogEntry.Person;
/**
* Atom protocol implementation of BlogEntry.
*/
public class AtomEntry extends BaseBlogEntry implements BlogEntry {
static final Log logger = LogFactory.getLog(AtomCollection.class);
String editURI = null;
AtomCollection collection = null;
AtomEntry(AtomBlog blog, AtomCollection collection) throws BlogClientException {
super(blog);
this.collection = collection;
}
AtomEntry(AtomCollection collection, ClientEntry entry) throws BlogClientException {
this((AtomBlog)collection.getBlog(), collection);
//clientEntry = entry;
copyFromRomeEntry(entry);
}
AtomEntry(AtomBlog blog, ClientEntry entry) throws BlogClientException {
super(blog);
//clientEntry = entry;
copyFromRomeEntry(entry);
}
/**
* {@inheritDoc}
*/
public String getToken() {
return editURI;
}
AtomCollection getCollection() {
return collection;
}
void setCollection(AtomCollection collection) {
this.collection = collection;
}
/**
* True if entry's token's are equal.
*/
public boolean equals(Object o) {
if (o instanceof AtomEntry) {
AtomEntry other = (AtomEntry)o;
if (other.getToken() != null && getToken() != null) {
return other.getToken().equals(getToken());
}
}
return false;
}
/**
* {@inheritDoc}
*/
public void save() throws BlogClientException {
boolean create = (getToken() == null);
if (create && getCollection() == null) {
throw new BlogClientException("Cannot save entry, no collection");
} else if (create) {
try {
ClientEntry clientEntry = collection.getClientCollection().createEntry();
copyToRomeEntry(clientEntry);
collection.getClientCollection().addEntry(clientEntry);
copyFromRomeEntry(clientEntry);
} catch (ProponoException ex) {
throw new BlogClientException("Error saving entry", ex);
}
} else {
try {
ClientEntry clientEntry = ((AtomBlog)getBlog()).getService().getEntry(getToken());
copyToRomeEntry(clientEntry);
clientEntry.update();
copyFromRomeEntry(clientEntry);
} catch (ProponoException ex) {
throw new BlogClientException("Error updating entry", ex);
}
}
}
/**
* {@inheritDoc}
*/
public void delete() throws BlogClientException {
if (getToken() == null) {
throw new BlogClientException("Cannot delete unsaved entry");
}
try {
ClientEntry clientEntry = ((AtomBlog)getBlog()).getService().getEntry(editURI);
clientEntry.remove();
} catch (ProponoException ex) {
throw new BlogClientException("Error removing entry", ex);
}
}
void copyFromRomeEntry(ClientEntry entry) {
id = entry.getId();
title = entry.getTitle();
editURI = entry.getEditURI();
List altlinks = entry.getAlternateLinks();
if (altlinks != null) {
for (Iterator iter = altlinks.iterator(); iter.hasNext();) {
Link link = (Link)iter.next();
if ("alternate".equals(link.getRel()) || link.getRel()==null) {
permalink = link.getHrefResolved();
break;
}
}
}
List contents = entry.getContents();
com.sun.syndication.feed.atom.Content romeContent = null;
if (contents != null && contents.size() > 0) {
romeContent = (com.sun.syndication.feed.atom.Content)contents.get(0);
}
if (romeContent != null) {
content = new BlogEntry.Content(romeContent.getValue());
content.setType(romeContent.getType());
content.setSrc(romeContent.getSrc());
}
if (entry.getCategories() != null) {
List cats = new ArrayList();
List romeCats = entry.getCategories();
for (Iterator iter=romeCats.iterator(); iter.hasNext();) {
com.sun.syndication.feed.atom.Category romeCat =
(com.sun.syndication.feed.atom.Category)iter.next();
BlogEntry.Category cat = new BlogEntry.Category();
cat.setId(romeCat.getTerm());
cat.setUrl(romeCat.getScheme());
cat.setName(romeCat.getLabel());
cats.add(cat);
}
categories = cats;
}
List authors = entry.getAuthors();
if (authors!=null && authors.size() > 0) {
com.sun.syndication.feed.atom.Person romeAuthor =
(com.sun.syndication.feed.atom.Person)authors.get(0);
if (romeAuthor != null) {
author = new Person();
author.setName(romeAuthor.getName());
author.setEmail(romeAuthor.getEmail());
author.setUrl(romeAuthor.getUrl());
}
}
publicationDate = entry.getPublished();
modificationDate = entry.getModified();
AppModule control = (AppModule)entry.getModule(AppModule.URI);
if (control != null && control.getDraft() != null) {
draft = control.getDraft().booleanValue();
} else {
draft = false;
}
}
Entry copyToRomeEntry(ClientEntry entry) {
if (id != null) {
entry.setId(id);
}
entry.setTitle(title);
if (author != null) {
com.sun.syndication.feed.atom.Person person =
new com.sun.syndication.feed.atom.Person();
person.setName(author.getName());
person.setEmail(author.getEmail());
person.setUrl(author.getUrl());
List authors = new ArrayList();
authors.add(person);
entry.setAuthors(authors);
}
if (content != null) {
com.sun.syndication.feed.atom.Content romeContent =
new com.sun.syndication.feed.atom.Content();
romeContent.setValue(content.getValue());
romeContent.setType(content.getType());
List contents = new ArrayList();
contents.add(romeContent);
entry.setContents(contents);
}
if (categories != null) {
List romeCats = new ArrayList();
for (Iterator iter=categories.iterator(); iter.hasNext();) {
BlogEntry.Category cat = (BlogEntry.Category)iter.next();
com.sun.syndication.feed.atom.Category romeCategory =
new com.sun.syndication.feed.atom.Category();
romeCategory.setTerm(cat.getId());
romeCategory.setScheme(cat.getUrl());
romeCategory.setLabel(cat.getName());
romeCats.add(romeCategory);
}
entry.setCategories(romeCats);
}
entry.setPublished((publicationDate == null) ? new Date() : publicationDate);
entry.setModified((modificationDate == null) ? new Date() : modificationDate);
List modules = new ArrayList();
AppModule control = new AppModuleImpl();
control.setDraft(new Boolean(draft));
modules.add(control);
entry.setModules(modules);
return entry;
}
}

View file

@ -1,72 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.atomprotocol;
import com.sun.syndication.propono.atom.client.ClientEntry;
import com.sun.syndication.propono.atom.client.ClientMediaEntry;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sun.syndication.propono.blogclient.BlogClientException;
/**
* Atom protocol implementation of BlogClient entry iterator.
*/
public class AtomEntryIterator implements Iterator {
static final Log logger = LogFactory.getLog(AtomEntryIterator.class);
private Iterator iterator = null;
private AtomCollection collection = null;
AtomEntryIterator(AtomCollection collection) throws BlogClientException {
try {
this.collection = collection;
iterator = collection.getClientCollection().getEntries();
} catch (Exception e) {
throw new BlogClientException("ERROR fetching collection", e);
}
}
/**
* True if more entries are available.
*/
public boolean hasNext() {
return iterator.hasNext();
}
/**
* Get next entry.
*/
public Object next() {
try {
ClientEntry entry = (ClientEntry)iterator.next();
if (entry instanceof ClientMediaEntry) {
return new AtomResource(collection, (ClientMediaEntry)entry);
} else {
return new AtomEntry(collection, entry);
}
} catch (Exception e) {
logger.error("ERROR fetching entry", e);
}
return null;
}
/**
* Remove is not supported.
*/
public void remove() {
// optional method, not implemented
}
}

View file

@ -1,134 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.atomprotocol;
import java.io.InputStream;
import com.sun.syndication.propono.blogclient.BlogClientException;
import com.sun.syndication.propono.blogclient.BlogEntry;
import com.sun.syndication.propono.blogclient.BlogResource;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.propono.atom.client.ClientAtomService;
import com.sun.syndication.propono.atom.client.ClientCollection;
import com.sun.syndication.propono.atom.client.ClientEntry;
import com.sun.syndication.propono.atom.client.ClientMediaEntry;
import java.util.Iterator;
import java.util.List;
/**
* Atom protocol implementation of BlogResource.
*/
public class AtomResource extends AtomEntry implements BlogResource {
private AtomCollection collection;
private byte[] bytes;
AtomResource(AtomCollection collection, String name, String contentType, byte[] bytes)
throws BlogClientException {
super((AtomBlog)collection.getBlog(), collection);
this.collection = collection;
this.bytes = bytes;
BlogEntry.Content rcontent = new BlogEntry.Content();
rcontent.setType(contentType);
setContent(rcontent);
}
AtomResource(AtomCollection collection, ClientMediaEntry entry)
throws BlogClientException {
super(collection, entry);
}
AtomResource(AtomBlog blog, ClientMediaEntry entry) throws BlogClientException {
super(blog, entry);
}
/**
* {@inheritDoc}
*/
public String getName() {
return getTitle();
}
byte[] getBytes() {
return bytes;
}
/**
* {@inheritDoc}
*/
public InputStream getAsStream() throws BlogClientException {
try {
return null; //((ClientMediaEntry)clientEntry).getAsStream();
} catch (Exception e) {
throw new BlogClientException("Error creating entry", e);
}
}
/**
* {@inheritDoc}
*/
public void save() throws BlogClientException {
try {
if (getToken() == null) {
ClientAtomService clientService = ((AtomBlog)getBlog()).getService();
ClientCollection clientCollection = collection.getClientCollection();
ClientMediaEntry clientEntry =
new ClientMediaEntry(clientService, clientCollection, getTitle(),
"", getContent().getType(), getBytes());
copyToRomeEntry(clientEntry);
collection.getClientCollection().addEntry(clientEntry);
this.editURI = clientEntry.getEditURI();
} else {
ClientAtomService clientService = ((AtomBlog)getBlog()).getService();
ClientMediaEntry clientEntry = (ClientMediaEntry)clientService.getEntry(editURI);
clientEntry.update();
}
} catch (Exception e) {
throw new BlogClientException("Error creating entry", e);
}
}
/**
* {@inheritDoc}
*/
public void update(byte[] newBytes) throws BlogClientException {
try {
//((ClientMediaEntry)clientEntry).setBytes(newBytes);
//clientEntry.update();
} catch (Exception e) {
throw new BlogClientException("Error creating entry", e);
}
}
void copyFromRomeEntry(ClientEntry entry) {
super.copyFromRomeEntry(entry);
List links = entry.getOtherLinks();
if (links != null) {
for (Iterator iter = links.iterator(); iter.hasNext();) {
Link link = (Link)iter.next();
if ("edit-media".equals(link.getRel())) {
id = link.getHrefResolved();
break;
}
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View file

@ -1,436 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.metaweblog;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Iterator;
import com.sun.syndication.propono.blogclient.BlogEntry;
import com.sun.syndication.propono.blogclient.Blog;
import com.sun.syndication.propono.blogclient.BlogClientException;
import com.sun.syndication.propono.blogclient.BlogResource;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
/**
* Blog implementation that uses a mix of Blogger and MetaWeblog API methods.
*/
public class MetaWeblogBlog implements Blog {
private String blogid;
private String name;
private URL url;
private String userName;
private String password;
private String appkey = "dummy";
private Map collections;
private XmlRpcClient xmlRpcClient = null;
/**
* {@inheritDoc}
*/
public String getName() { return name; }
/**
* {@inheritDoc}
*/
public String getToken() { return blogid; }
/**
* String representation of blog, returns the name.
*/
public String toString() { return getName(); }
private XmlRpcClient getXmlRpcClient() {
if (xmlRpcClient == null) {
XmlRpcClientConfigImpl xmlrpcConfig = new XmlRpcClientConfigImpl();
xmlrpcConfig.setServerURL(url);
xmlRpcClient = new XmlRpcClient();
xmlRpcClient.setConfig(xmlrpcConfig);
}
return xmlRpcClient;
}
MetaWeblogBlog(String blogid, String name,
URL url, String userName, String password) {
this.blogid = blogid;
this.name = name;
this.url = url;
this.userName = userName;
this.password = password;
this.collections = new TreeMap();
collections.put("entries",
new MetaWeblogBlogCollection(this, "entries", "Entries", "entry"));
collections.put("resources",
new MetaWeblogBlogCollection(this, "resources", "Resources", "*"));
}
MetaWeblogBlog(String blogId, String name,
URL url, String userName, String password, String appkey) {
this(blogId, name, url, userName, password);
this.appkey = appkey;
}
/**
* {@inheritDoc}
*/
public BlogEntry newEntry() {
return new MetaWeblogEntry(this, new HashMap());
}
String saveEntry(BlogEntry entry) throws BlogClientException {
Blog.Collection col = (Blog.Collection)collections.get("entries");
return col.saveEntry(entry);
}
/**
* {@inheritDoc}
*/
public BlogEntry getEntry(String id) throws BlogClientException {
try {
Map result = (Map)
getXmlRpcClient().execute("metaWeblog.getPost", new Object[] {id, userName, password});
return new MetaWeblogEntry(this, result);
} catch (Exception e) {
throw new BlogClientException("ERROR: XML-RPC error getting entry", e);
}
}
void deleteEntry(String id) throws BlogClientException {
try {
getXmlRpcClient().execute("blogger.deletePost",
new Object[] {appkey, id, userName, password, Boolean.FALSE});
} catch (Exception e) {
throw new BlogClientException("ERROR: XML-RPC error getting entry", e);
}
}
/**
* {@inheritDoc}
*/
public Iterator getEntries() throws BlogClientException {
return new EntryIterator();
}
/**
* {@inheritDoc}
*/
public BlogResource newResource(String name, String contentType, byte[] bytes) throws BlogClientException {
return new MetaWeblogResource(this, name, contentType, bytes);
}
String saveResource(MetaWeblogResource resource) throws BlogClientException {
Blog.Collection col = (Blog.Collection)collections.get("resources");
return col.saveResource(resource);
}
BlogResource getResource(String token) throws BlogClientException {
return null;
}
/**
* {@inheritDoc}
*/
public Iterator getResources() throws BlogClientException {
return new NoOpIterator();
}
void deleteResource(BlogResource resource) throws BlogClientException {
// no-op
}
/**
* {@inheritDoc}
*/
public List getCategories() throws BlogClientException {
ArrayList ret = new ArrayList();
try {
Object result =
getXmlRpcClient().execute ("metaWeblog.getCategories",
new Object[] {blogid, userName, password});
if (result != null && result instanceof HashMap) {
// Standard MetaWeblog API style: struct of struts
Map catsmap = (Map)result;
Iterator keys = catsmap.keySet().iterator();
while (keys.hasNext()) {
String key = (String)keys.next();
Map catmap = (Map)catsmap.get(key);
BlogEntry.Category category = new BlogEntry.Category(key);
category.setName((String)catmap.get("description"));
// catmap.get("htmlUrl");
// catmap.get("rssUrl");
ret.add(category);
}
} else if (result != null && result instanceof Object[]) {
// Wordpress style: array of structs
Object[] resultArray = (Object[])result;
for (int i=0; i<resultArray.length; i++) {
Map catmap = (Map)resultArray[i];
String categoryId = (String)catmap.get("categoryId");
String categoryName = (String)catmap.get("categoryName");
BlogEntry.Category category = new BlogEntry.Category(categoryId);
category.setName(categoryName);
ret.add(category);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
private HashMap createPostStructure(BlogEntry entry) {
return ((MetaWeblogEntry)entry).toPostStructure();
}
/**
* {@inheritDoc}
*/
public List getCollections() throws BlogClientException {
return new ArrayList(collections.values());
}
/**
* {@inheritDoc}
*/
public Blog.Collection getCollection(String token) throws BlogClientException {
return (Blog.Collection)collections.get(token);
}
//-------------------------------------------------------------------------
/** MetaWeblog API impplementation of Blog.Collection */
public class MetaWeblogBlogCollection implements Blog.Collection {
private String accept = null;
private String title = null;
private String token = null;
private Blog blog = null;
/**
* @param token Identifier for collection, unique within blog
* @param title Title of collection
* @param accept Content types accepted, either "entry" or "*"
*/
public MetaWeblogBlogCollection(Blog blog, String token, String title, String accept) {
this.blog = blog;
this.accept = accept;
this.title = title;
this.token = token;
}
/**
* {@inheritDoc}
*/
public String getTitle() {
return title;
}
/**
* {@inheritDoc}
*/
public String getToken() {
return token;
}
/**
* {@inheritDoc}
*/
public List getAccepts() {
return Collections.singletonList(accept);
}
/**
* {@inheritDoc}
*/
public BlogResource newResource(String name, String contentType, byte[] bytes) throws BlogClientException {
return blog.newResource(name, contentType, bytes);
}
/**
* {@inheritDoc}
*/
public BlogEntry newEntry() throws BlogClientException {
return blog.newEntry();
}
/**
* {@inheritDoc}
*/
public boolean accepts(String ct) {
if (accept.equals("*")) {
// everything accepted
return true;
} else if (accept.equals("entry") && ct.equals("application/metaweblog+xml")) {
// entries only accepted and "application/metaweblog+xml" means entry
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
public Iterator getEntries() throws BlogClientException {
Iterator ret = null;
if (accept.equals("entry")) {
ret = MetaWeblogBlog.this.getEntries();
} else {
ret = MetaWeblogBlog.this.getResources();
}
return ret;
}
/**
* {@inheritDoc}
*/
public String saveEntry(BlogEntry entry) throws BlogClientException {
String ret = entry.getId();
if (entry.getId() == null) {
try {
ret = (String)getXmlRpcClient().execute("metaWeblog.newPost",
new Object[] {blogid, userName, password, createPostStructure(entry), new Boolean(!entry.getDraft()) });
} catch (Exception e) {
throw new BlogClientException("ERROR: XML-RPC error saving new entry", e);
}
} else {
try {
getXmlRpcClient().execute("metaWeblog.editPost",
new Object[] {entry.getId(),userName,password,createPostStructure(entry),new Boolean(!entry.getDraft())});
} catch (Exception e) {
throw new BlogClientException("ERROR: XML-RPC error updating entry", e);
}
}
return ret;
}
/**
* {@inheritDoc}
*/
public String saveResource(BlogResource res) throws BlogClientException {
MetaWeblogResource resource = (MetaWeblogResource)res;
try {
HashMap resmap = new HashMap();
resmap.put("name", resource.getName());
resmap.put("type", resource.getContent().getType());
resmap.put("bits", resource.getBytes());
Map result = (Map)
getXmlRpcClient().execute("metaWeblog.newMediaObject",
new Object[] {blogid, userName, password, resmap});
String url = (String)result.get("url");
res.getContent().setSrc(url);
return url;
} catch (Exception e) {
throw new BlogClientException("ERROR: loading or uploading file", e);
}
}
/**
* {@inheritDoc}
*/
public List getCategories() throws BlogClientException {
return MetaWeblogBlog.this.getCategories();
}
/**
* {@inheritDoc}
*/
public Blog getBlog() {
return blog;
}
}
//-------------------------------------------------------------------------
/**
* Iterates over MetaWeblog API entries.
*/
public class EntryIterator implements Iterator {
private int pos = 0;
private boolean eod = false;
private static final int BUFSIZE = 30;
private List results = null;
/**
* Iterator for looping over MetaWeblog API entries.
*/
public EntryIterator() throws BlogClientException {
getNextEntries();
}
/**
* Returns true if more entries are avialable.
*/
public boolean hasNext() {
if (pos == results.size() && !eod) {
try { getNextEntries(); } catch (Exception ignored) {}
}
return (pos < results.size());
}
/**
* Get next entry.
*/
public Object next() {
Map entryHash = (Map)results.get(pos++);
return new MetaWeblogEntry(MetaWeblogBlog.this, entryHash);
}
/**
* Remove is not implemented.
*/
public void remove() {
}
private void getNextEntries() throws BlogClientException {
int requestSize = pos + BUFSIZE;
try {
Object[] resultsArray = (Object[])
getXmlRpcClient().execute("metaWeblog.getRecentPosts",
new Object[] {blogid, userName, password, new Integer(requestSize)} );
results = Arrays.asList(resultsArray);
} catch (Exception e) {
throw new BlogClientException("ERROR: XML-RPC error getting entry", e);
}
if (results.size() < requestSize) eod = true;
}
}
//-------------------------------------------------------------------------
/**
* No-op iterator.
*/
public class NoOpIterator implements Iterator {
/**
* No-op
*/
public boolean hasNext() {
return false;
}
/**
* No-op
*/
public Object next() {
return null;
}
/**
* No-op
*/
public void remove() {}
}
}

View file

@ -1,105 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.metaweblog;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import com.sun.syndication.propono.blogclient.BlogConnection;
import com.sun.syndication.propono.blogclient.Blog;
import com.sun.syndication.propono.blogclient.BlogClientException;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
/**
* BlogClient implementation that uses a mix of Blogger and MetaWeblog API methods.
*/
public class MetaWeblogConnection implements BlogConnection {
private URL url = null;
private String userName = null;
private String password = null;
private String appkey = "null";
private Map blogs = null;
private XmlRpcClient xmlRpcClient = null;
public MetaWeblogConnection(String url, String userName, String password)
throws BlogClientException {
this.userName = userName;
this.password = password;
try {
this.url = new URL(url);
blogs = createBlogMap();
} catch (Throwable t) {
throw new BlogClientException("ERROR connecting to server", t);
}
}
private XmlRpcClient getXmlRpcClient() {
if (xmlRpcClient == null) {
XmlRpcClientConfigImpl xmlrpcConfig = new XmlRpcClientConfigImpl();
xmlrpcConfig.setServerURL(url);
xmlRpcClient = new XmlRpcClient();
xmlRpcClient.setConfig(xmlrpcConfig);
}
return xmlRpcClient;
}
/**
* {@inheritDoc}
*/
public List getBlogs() {
return new ArrayList(blogs.values());
}
/**
* {@inheritDoc}
*/
private Map createBlogMap() throws XmlRpcException, IOException {
Map blogMap = new HashMap();
Object[] results = (Object[])getXmlRpcClient().execute("blogger.getUsersBlogs",
new Object[] {appkey, userName, password});
for (int i = 0; i < results.length; i++) {
Map blog = (Map)results[i];
String blogid = (String)blog.get("blogid");
String name = (String)blog.get("blogName");
blogMap.put(blogid, new MetaWeblogBlog(blogid, name, url, userName, password));
}
return blogMap;
}
/**
* {@inheritDoc}
*/
public Blog getBlog(String token) {
return (Blog)blogs.get(token);
}
/**
* {@inheritDoc}
*/
public void setAppkey(String appkey) {
this.appkey = appkey;
}
}

View file

@ -1,122 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.metaweblog;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import com.sun.syndication.propono.blogclient.BlogClientException;
import com.sun.syndication.propono.blogclient.BaseBlogEntry;
import com.sun.syndication.propono.blogclient.BlogEntry;
import java.util.Map;
/**
* MetaWeblog API implementation of an entry.
*/
public class MetaWeblogEntry extends BaseBlogEntry {
MetaWeblogEntry(MetaWeblogBlog blog, Map entryMap) {
super(blog);
id = (String)entryMap.get("postid");
content = new Content((String)entryMap.get("description"));
// let's pretend MetaWeblog API has a content-type
content.setType("application/metaweblog+xml");
// no way to tell if entry is draft or not
draft = false;
title = (String)entryMap.get("title");
publicationDate = (Date)entryMap.get("dateCreated");
permalink = (String)entryMap.get("permaLink");
// AlexisMP: fix to get the author value populated.
author.setName( (String)entryMap.get("userid") );
author.setEmail( (String)entryMap.get("author") );
categories = new ArrayList();
Object[] catArray = (Object[])entryMap.get("categories");
if (catArray != null) {
for (int i=0; i<catArray.length; i++) {
Category cat = new Category((String)catArray[i]);
categories.add(cat);
}
}
}
/**
* {@inheritDoc}
*/
public String getToken() {
return id;
}
/**
* True if tokens are equal
*/
public boolean equals(Object o) {
if (o instanceof MetaWeblogEntry) {
MetaWeblogEntry other = (MetaWeblogEntry)o;
if (other.id != null && id != null) {
return other.id.equals(id);
}
}
return false;
}
/**
* {@inheritDoc}
*/
public void save() throws BlogClientException {
id = ((MetaWeblogBlog)getBlog()).saveEntry(this);
}
/**
* {@inheritDoc}
*/
public void delete() throws BlogClientException {
((MetaWeblogBlog)getBlog()).deleteEntry(id);
}
HashMap toPostStructure() {
HashMap struct = new HashMap();
if (getTitle() != null) {
struct.put("title", getTitle());
}
if (getContent() != null && getContent().getValue() != null) {
struct.put("description", getContent().getValue());
}
if (getCategories() != null && getCategories().size() > 0) {
List catArray = new ArrayList();
List cats = getCategories();
for (int i=0; i<cats.size(); i++) {
BlogEntry.Category cat = (BlogEntry.Category)cats.get(i);
catArray.add(cat.getName());
}
struct.put("categories", catArray);
}
if (getPublicationDate() != null) {
struct.put("dateCreated", getPublicationDate());
}
if (getId() != null) {
struct.put("postid", getId());
}
return struct;
}
}

View file

@ -1,112 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.blogclient.metaweblog;
import com.sun.syndication.propono.blogclient.BlogClientException;
import java.io.InputStream;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import com.sun.syndication.propono.blogclient.BlogResource;
import java.util.HashMap;
/**
* MetaWeblog API implementation of an resource entry.
*/
public class MetaWeblogResource extends MetaWeblogEntry implements BlogResource {
private MetaWeblogBlog blog;
private String name;
private String contentType;
private byte[] bytes;
MetaWeblogResource(MetaWeblogBlog blog,
String name, String contentType, byte[] bytes) {
super(blog, new HashMap());
this.blog = blog;
this.name = name;
this.contentType = contentType;
this.bytes = bytes;
this.content = new Content();
this.content.setType(contentType);
}
/**
* {@inheritDoc}
*/
public String getName() {
return name;
}
/**
* {@inheritDoc}
*/
public String getToken() {
return null;
}
/**
* Get content-type of associated media resource.
*/
public String getContentType() {
return contentType;
}
/**
* Get media resource as input stream.
*/
public InputStream getAsStream() throws BlogClientException {
HttpClient httpClient = new HttpClient();
GetMethod method = new GetMethod(permalink);
try {
httpClient.executeMethod(method);
} catch (Exception e) {
throw new BlogClientException("ERROR: error reading file", e);
}
if (method.getStatusCode() != 200) {
throw new BlogClientException("ERROR HTTP status=" + method.getStatusCode());
}
try {
return method.getResponseBodyAsStream();
} catch (Exception e) {
throw new BlogClientException("ERROR: error reading file", e);
}
}
/**
* {@inheritDoc}
*/
public void save() throws BlogClientException {
blog.saveResource(this);
}
/**
* {@inheritDoc}
*/
public void update(byte[] bytes) throws BlogClientException {
this.bytes = bytes;
save();
}
/**
* Get resource data as byte array.
*/
public byte[] getBytes() {
return bytes;
}
/**
* Not supported by MetaWeblog API
*/
public void delete() throws BlogClientException {
}
}

View file

@ -1,153 +0,0 @@
/*
* 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.utils;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* Base Propono exception class.
*/
public class ProponoException extends Exception {
private Throwable mRootCause = null;
private String longMessage = null;
/**
* Construct emtpy exception object.
*/
public ProponoException() {
super();
}
/**
* Construct ProponoException with message string.
* @param s Error message string.
*/
public ProponoException(String s) {
super(s);
}
/**
* Construct ProponoException with message string.
* @param s Error message string.
*/
public ProponoException(String s, String longMessage) {
super(s);
this.longMessage = longMessage;
}
/**
* Construct ProponoException, wrapping existing throwable.
* @param s Error message
* @param t Existing connection to wrap.
*/
public ProponoException(String s, Throwable t) {
super(s);
mRootCause = t;
}
/**
* Construct ProponoException, wrapping existing throwable.
* @param s Error message
* @param t Existing connection to wrap.
*/
public ProponoException(String s, String longMessge, Throwable t) {
super(s);
mRootCause = t;
this.longMessage = longMessage;
}
/**
* Construct ProponoException, wrapping existing throwable.
* @param t Existing exception to be wrapped.
*/
public ProponoException(Throwable t) {
mRootCause = t;
}
/**
* Get root cause object, or null if none.
* @return Root cause or null if none.
*/
public Throwable getRootCause() {
return mRootCause;
}
/**
* Get root cause message.
* @return Root cause message.
*/
public String getRootCauseMessage() {
String rcmessage = null;
if (getRootCause()!=null) {
if (getRootCause().getCause()!=null) {
rcmessage = getRootCause().getCause().getMessage();
}
rcmessage = (rcmessage == null) ? getRootCause().getMessage() : rcmessage;
rcmessage = (rcmessage == null) ? super.getMessage() : rcmessage;
rcmessage = (rcmessage == null) ? "NONE" : rcmessage;
}
return rcmessage;
}
/**
* Print stack trace for exception and for root cause exception if htere is one.
* @see java.lang.Throwable#printStackTrace()
*/
public void printStackTrace() {
super.printStackTrace();
if (mRootCause != null) {
System.out.println("--- ROOT CAUSE ---");
mRootCause.printStackTrace();
}
}
/**
* Print stack trace for exception and for root cause exception if htere is one.
* @param s Stream to print to.
*/
public void printStackTrace(PrintStream s) {
super.printStackTrace(s);
if (mRootCause != null) {
s.println("--- ROOT CAUSE ---");
mRootCause.printStackTrace(s);
}
}
/**
* Print stack trace for exception and for root cause exception if htere is one.
* @param s Writer to write to.
*/
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
if (null != mRootCause) {
s.println("--- ROOT CAUSE ---");
mRootCause.printStackTrace(s);
}
}
}

View file

@ -1,268 +0,0 @@
/*
* Copyright 2007 Dave Johnson (Blogapps project)
*
* 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.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Parent;
/**
* Utilities for file I/O and string manipulation.
*/
public class Utilities {
private static final String LS = System.getProperty("line.separator");
/**
* Returns the contents of the file in a byte array (from JavaAlmanac).
*/
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
/**
* Read input from stream and into string.
*/
public static String streamToString(InputStream is) throws IOException {
StringBuffer sb = new StringBuffer();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append(LS);
}
return sb.toString();
}
/**
* Copy input stream to output stream using 8K buffer.
*/
public static void copyInputToOutput(
InputStream input,
OutputStream output)
throws IOException {
BufferedInputStream in = new BufferedInputStream(input);
BufferedOutputStream out = new BufferedOutputStream(output);
byte buffer[] = new byte[8192];
for (int count = 0; count != -1;) {
count = in.read(buffer, 0, 8192);
if (count != -1)
out.write(buffer, 0, count);
}
try {
in.close();
out.close();
} catch (IOException ex) {
throw new IOException("Closing file streams, " + ex.getMessage());
}
}
/**
* Replaces occurences of non-alphanumeric characters with a supplied char.
*/
public static String replaceNonAlphanumeric(String str, char subst) {
StringBuffer ret = new StringBuffer(str.length());
char[] testChars = str.toCharArray();
for (int i = 0; i < testChars.length; i++) {
if (Character.isLetterOrDigit(testChars[i])) {
ret.append(testChars[i]);
} else {
ret.append( subst );
}
}
return ret.toString();
}
/**
* Convert string to string array.
*/
public static String[] stringToStringArray(String instr, String delim)
throws NoSuchElementException, NumberFormatException {
StringTokenizer toker = new StringTokenizer(instr, delim);
String stringArray[] = new String[toker.countTokens()];
int i = 0;
while (toker.hasMoreTokens()) {
stringArray[i++] = toker.nextToken();
}
return stringArray;
}
/**
* Convert string array to string.
*/
public static String stringArrayToString(String[] stringArray, String delim) {
String ret = "";
for (int i = 0; i < stringArray.length; i++) {
if (ret.length() > 0)
ret = ret + delim + stringArray[i];
else
ret = stringArray[i];
}
return ret;
}
static Pattern absoluteURIPattern = Pattern.compile("^[a-z0-9]*:.*$");
private static boolean isAbsoluteURI(String uri) {
return absoluteURIPattern.matcher(uri).find();
}
private static boolean isRelativeURI(String uri) {
return !isAbsoluteURI(uri);
}
/**
* }
* Resolve URI based considering xml:base and baseURI.
* @param baseURI Base URI of feed
* @param parent Parent from which to consider xml:base
* @param url URL to be resolved
*/
private static String resolveURI(String baseURI, Parent parent, String url) {
if (isRelativeURI(url)) {
url = (!".".equals(url) && !"./".equals(url)) ? url : "";
// Relative URI with parent
if (parent != null && parent instanceof Element) {
// Do we have an xml:base?
String xmlbase = ((Element)parent).getAttributeValue(
"base", Namespace.XML_NAMESPACE);
if (xmlbase != null && xmlbase.trim().length() > 0) {
if (isAbsoluteURI(xmlbase)) {
// Absolute xml:base, so form URI right now
if (url.startsWith("/")) {
// Host relative URI
int slashslash = xmlbase.indexOf("//");
int nextslash = xmlbase.indexOf("/", slashslash + 2);
if (nextslash != -1) xmlbase = xmlbase.substring(0, nextslash);
return formURI(xmlbase, url);
}
if (!xmlbase.endsWith("/")) {
// Base URI is filename, strip it off
xmlbase = xmlbase.substring(0, xmlbase.lastIndexOf("/"));
}
return formURI(xmlbase, url);
} else {
// Relative xml:base, so walk up tree
return resolveURI(baseURI, parent.getParent(),
stripTrailingSlash(xmlbase) + "/"+ stripStartingSlash(url));
}
}
// No xml:base so walk up tree
return resolveURI(baseURI, parent.getParent(), url);
// Relative URI with no parent (i.e. top of tree), so form URI right now
} else if (parent == null || parent instanceof Document) {
return formURI(baseURI, url);
}
}
return url;
}
/**
* Form URI by combining base with append portion and giving
* special consideration to append portions that begin with ".."
* @param base Base of URI, may end with trailing slash
* @param append String to append, may begin with slash or ".."
*/
private static String formURI(String base, String append) {
base = stripTrailingSlash(base);
append = stripStartingSlash(append);
if (append.startsWith("..")) {
String ret = null;
String[] parts = append.split("/");
for (int i=0; i<parts.length; i++) {
if ("..".equals(parts[i])) {
int last = base.lastIndexOf("/");
if (last != -1) {
base = base.substring(0, last);
append = append.substring(3, append.length());
}
else break;
}
}
}
return base + "/" + append;
}
/**
* Strip starting slash from beginning of string.
*/
private static String stripStartingSlash(String s) {
if (s != null && s.startsWith("/")) {
s = s.substring(1, s.length());
}
return s;
}
/**
* Strip trailing slash from end of string.
*/
private static String stripTrailingSlash(String s) {
if (s != null && s.endsWith("/")) {
s = s.substring(0, s.length() - 1);
}
return s;
}
}