/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* 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.
*/
package com.hphoto.server;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.*;
import org.apache.hadoop.conf.Configuration;
import org.json.JSONException;
import org.w3c.dom.*;
import com.hphoto.bean.Category;
import com.hphoto.bean.Image;
import com.hphoto.bean.UserProfile;
import com.hphoto.util.I18nUtil;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/** Present search results using A9's OpenSearch extensions to RSS, plus a few
* Nutch-specific extensions. */
public class ApiServlet extends HttpServlet {
private static final Map NS_MAP = new HashMap();
static {
NS_MAP.put("opensearch", "http://a9.com/-/spec/opensearchrss/1.0/");
NS_MAP.put("atom", "http://www.w3.org/2005/Atom");
NS_MAP.put("photo", "http://www.pheed.com/pheed/");
NS_MAP.put("media", "http://search.yahoo.com/mrss/");
}
private String key = "com.hphoto.message.api";
private static final Set SKIP_DETAILS = new HashSet();
static {
SKIP_DETAILS.add("url"); // redundant with RSS link
SKIP_DETAILS.add("title"); // redundant with RSS title
}
private Configuration conf;
private TableServer server;
public void init(ServletConfig config) throws ServletException {
if(server != null){
return;
}
try {
ServletContext context = config.getServletContext();
this.server = (TableServer)context.getAttribute("hphoto.tableServer");
this.conf = (Configuration)context.getAttribute("hphoto.conf");
} catch (Exception e) {
throw new ServletException(e);
}
}
public void addCategory(Document doc,Element channel,HttpServletRequest request){
assert(request.getParameter("user") != null);
String requestUrl = request.getRequestURL().toString();
String base = "http://" +request.getServerName() + (request.getLocalPort() == 80 ? "" : ":"+Integer.toString(request.getLocalPort()));
Category[] categories = null;
UserProfile[] users = null;
String owner = request.getParameter("user") ;
String feed = request.getParameter("feed");
String language = request.getParameter("hl");
String kind = request.getParameter("kind");
String albumid = request.getParameter("albumid");
//Local local = language == null ? request.getLocale() : new Locale(language);
boolean all = request.getParameter("acess") != null && request.getParameter("acess").equals("all");
boolean api = feed != null && feed.equals("api");
try {
users = server.getUser(owner,1);
categories = server.getCategories(owner);
} catch (IOException e) {
e.printStackTrace();
return;
}
if(users ==null || users.length == 0){
return;
}
addNode(doc, channel, "atom","id",base+"/feed/"+feed+"/user/"+owner);
addNode(doc, channel, "lastBuildDate",(new Date()).toString());
addNode(doc, channel, "title", owner +" "+ I18nUtil.getText(key,"title",request.getLocale()));
addNode(doc, channel, "description", "");
//add base,not complete
addNode(doc, channel, "link", base + "/" + owner);
addNode(doc, channel, "managingEditor" , owner);
addNode(doc, channel, "generator", "hphoto.com");
addNode(doc, channel, "opensearch", "totalResults", ""+(categories != null?categories.length:0));
//addNode(doc, channel, "opensearch", "startIndex", ""+1);
//addNode(doc, channel, "opensearch", "itemsPerPage", ""+1000);
Element image = addNode(doc, channel, "image");
addNode(doc, image, "url", base + "/image/"+owner+"/"+"AHHYILU"+"/s48-c/"+owner);
addNode(doc, image, "title", owner + " " + I18nUtil.getText(key,"title",request.getLocale()));
addNode(doc, image, "link",base + "/" + owner);
//channel
if(categories != null){
for(Category category:categories){
if(!all){
if(!category.isOpened() || category.getCount() < 1){
continue;
}
}
Element item = addNode(doc, channel, "item");
addNode(doc, item, "pubDate" , category.getCreatdate().toString());
addNode(doc, item, "atom", "updated", category.getLastupload().toString() );
addNode(doc, item, "title", category.getName());
addNode(doc, item, "description", getDescription(api,base,owner,category,I18nUtil.getLoacl(request)));
addNode(doc, item, "link", "");
addNode(doc, item, "author",owner);
if(api){
//api data here
}
Element media = addNode(doc,item,"media:group");
Element title = addNode(doc, media, "media", "title", category.getName());
addAttribute(doc, title, "type" , "plain");
Element descript = addNode(doc, media, "media", "descript", "");
addAttribute(doc, descript, "type" , "plain");
addNode(doc, media, "media", "keywords", "");
String lablename = category.getLablename();
String imgurl = category.getImgurl();
String id = imgurl.substring(imgurl.lastIndexOf('/')+1,imgurl.lastIndexOf('.'));
String img = "/image/"+owner+"/"+lablename+"/"+id+".jpg";
String thumbnailImg = "/image/"+owner+"/"+lablename+"/s"+160+"-c/"+id+".jpg";
Element content = addNode(doc, media, "media", "content", "");
addAttribute(doc, content, "url" , base+img);
addAttribute(doc, content, "type", "image/jpeg");
addAttribute(doc, content, "medium", "image");
Element thum = addNode(doc, media, "media", "thumbnail", "");
addAttribute(doc, thum, "url" , base+thumbnailImg);
addAttribute(doc, thum, "height", "160");
addAttribute(doc, thum, "width", "160");
addNode(doc, media, "media", "credit", owner);
}
}
}
public void addPhoto(Document doc,Element channel,HttpServletRequest request){
assert(request.getParameter("user") != null);
assert(request.getParameter("album") != null);
String requestUrl = request.getRequestURL().toString();
String base = "http://" +request.getServerName() + (request.getLocalPort() == 80 ? "" : ":"+Integer.toString(request.getLocalPort()));
Image[] images = null;
UserProfile[] users = null;
Category category = null;
String owner = request.getParameter("user") ;
String album = request.getParameter("album");
String authKey = request.getParameter("authKey");
boolean api = request.getParameter("feed") != null && request.getParameter("feed").equals("api");
try {
users = server.getUser(owner,1);
images = server.getImages(owner,album);
category = server.getCategory(owner,album);
} catch (IOException e) {
return;
}
if(users ==null || users.length == 0){
return;
}
if(category==null){
return;
}
if(!category.isOpened()){
if(!category.getAuthkey().equals(authKey)){
return;
}
}
addNode(doc, channel, "atom","id",base+"/feed/"+request.getParameter("feed")+"/user/"+owner+"/album/"+album);
addNode(doc, channel, "lastBuildDate",(new Date()).toString());
addNode(doc, channel, "title", owner +" "+ I18nUtil.getText(key,"title",I18nUtil.getLoacl(request)));
addNode(doc, channel, "description", "");
//add base,not complete
addNode(doc, channel, "link", base + "/" + owner +"/" + album +(category.getAuthkey() != null ? "?authKey="+ category.getAuthkey(): ""));
addNode(doc, channel, "managingEditor" , owner);
addNode(doc, channel, "generator", "hphoto.com");
addNode(doc, channel, "opensearch", "totalResults", ""+(images != null?images.length:0));
addNode(doc, channel, "opensearch", "startIndex", ""+1);
addNode(doc, channel, "opensearch", "itemsPerPage", ""+1000);
String lablename = category.getLablename();
String imgurl = category.getImgurl();
String id = imgurl.substring(imgurl.lastIndexOf('/')+1,imgurl.lastIndexOf('.'));
String img = "/image/"+owner+"/"+lablename+"/s"+160+"-c/"+id+".jpg";
Element timage = addNode(doc, channel, "image");
addNode(doc, timage, "url", base + img);
addNode(doc, timage, "title", category.getName());
addNode(doc, timage, "link",base + "/" + owner +"/" + lablename + (category.getAuthkey() != null ? "?authKey="+ category.getAuthkey(): ""));
if(api){
//api data here
}
if(images != null){
//channel
for(Image image:images){
Element item = addNode(doc, channel, "item");
addNode(doc, item, "pubDate" , image.getTimestamp().toString());
addNode(doc, item, "atom", "updated", image.getTimestamp().toString() );
addNode(doc, item, "title", image.getFileName());
addNode(doc, item, "description", getDescription(api,base,owner,category,image,I18nUtil.getLoacl(request)));
addNode(doc, item, "link", "");
addNode(doc, item, "author",owner);
if(api){
//api data here
}
Element media = addNode(doc,item,"media:group");
Element title = addNode(doc, media, "media", "title", image.getFileName());
addAttribute(doc, title, "type" , "plain");
Element descript = addNode(doc, media, "media", "descript", "");
addAttribute(doc, descript, "type" , "plain");
addNode(doc, media, "media", "keywords", "");
String img1 = base+"/image/"+owner+"/"+lablename+"/"+id+".jpg";
String thumbnailImg = base+"/image/"+owner+"/"+lablename+"/s"+288+"/"+image.getId()+".jpg";
Element content = addNode(doc, media, "media", "content", "");
addAttribute(doc, content, "url" ,img1);
addAttribute(doc, content, "type", "image/jpeg");
addAttribute(doc, content, "medium", "image");
int[] value=getWidthAndHeight(image.getWidth(),image.getHeight(),288);
Element thum = addNode(doc, media, "media", "thumbnail", "");
addAttribute(doc, thum, "url" , thumbnailImg);
addAttribute(doc, thum, "height", Integer.toString(value[1]));
addAttribute(doc, thum, "width", Integer.toString(value[0]));
addNode(doc, media, "media", "credit", owner);
}
}
}
private int[] getWidthAndHeight(int width,int height,int max){
int[] value = new int[2];
float rate = (float)width/(float)height;
if(rate > 1){
value[0] = max;
value[1] = (int)(max/rate);
}else{
value[0] = (int) (max *rate);
value[1] = max;
}
return value;
}
private String getDescription(boolean isApi,String base,String owner,Category category,Locale locale){
if(isApi)
return "";
StringBuilder sb = new StringBuilder();
String lablename = category.getLablename();
String imgurl = category.getImgurl();
String id = imgurl.substring(imgurl.lastIndexOf('/')+1,imgurl.lastIndexOf('.'));
String thumbnailImg = base + "/image/"+owner+"/"+lablename+"/s"+160+"-c/"+id+".jpg";
java.text.SimpleDateFormat dateFormatter = new java.text.SimpleDateFormat(I18nUtil.getText(key,"data.format",locale));
sb.append("<table><tr><td style=\"padding: 0 5px\">");
sb.append("<a href=\""+base+"/"+owner+"/"+category.getLablename()+(category.getAuthkey() != null ? "?authKey="+ category.getAuthkey(): "")+"\"><img src=\""+thumbnailImg+"\" style=\"border:1px solid #5C7FB9\" src=\"\" alt=\""+category.getName()+"\"/></a></td>");
sb.append("<td valign=\"top\"><p><font color=\"#333333\"></font></p>");
sb.append("<font color=\"#6B6B6B\">"+I18nUtil.getText(key,"date",locale)+ "</font><font color=\"#333333\">"+dateFormatter.format(category.getCreatdate())+"</font><br/>");
sb.append("<font color=\"#6B6B6B\"> "+I18nUtil.getText(key,"album.number",locale)+"</font><font color=\"#333333\">"+category.getCount()+"</font><br/>");
sb.append("<p><a href=\""+base+"/"+owner+"/"+category.getLablename()+(category.getAuthkey() != null ? "?authKey="+ category.getAuthkey(): "")+"\"><font color=\"#112ABB\">"+I18nUtil.getText(key,"view",locale)+"</font></a></p></td></tr></table>");
return sb.toString();
}
private String getDescription(boolean isApi,String base,String owner,Category category,Image image,Locale locale){
if(isApi)
return "";
String imgUri = base + "/image/"+owner+"/"+category.getLablename()+"/s"+288+"/"+image.getId()+".jpg";
StringBuilder sb = new StringBuilder();
java.text.SimpleDateFormat dateFormatter = new java.text.SimpleDateFormat(I18nUtil.getText(key,"data.format",locale));
sb.append("<table><tr><td style=\"padding: 0 5px\">");
sb.append("<a href=\""+base+"/"+owner+"/"+category.getLablename()+"/"+image.getId()+(category.getAuthkey() != null ? "?authKey="+ category.getAuthkey(): "")+"\"><img src=\""+imgUri+"\" style=\"border:1px solid #5C7FB9\" src=\"\" alt=\""+image.getFileName()+"\"/></a></td>");
sb.append("<td valign=\"top\"><p><font color=\"#333333\"></font></p><font color=\"#6B6B6B\">"+I18nUtil.getText(key,"date",locale)+"</font><font color=\"#333333\">"+dateFormatter.format(image.getTimestamp())+"</font><br/>");
sb.append("<p><a href=\""+base+"/"+owner+"/"+category.getLablename()+"/"+image.getId()+(category.getAuthkey() != null ? "?authKey="+ category.getAuthkey(): "")+"\"><font color=\"#112ABB\">"+I18nUtil.getText(key,"view.photo",locale)+"</font></a></p></td></tr></table>");
return sb.toString();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// get parameters from request
request.setCharacterEncoding("UTF-8");
// the query language
String lang = request.getParameter("hl");
String kind = request.getParameter("kind");
String alt = request.getParameter("alt");
String owner = request.getParameter("user") ;
String feed = request.getParameter("feed");
String albumid = request.getParameter("album");
if(lang != null){
if(lang.indexOf('_') == -1){
//throw
}
String language = lang.substring(0, lang.indexOf('_'));
String count = lang.substring(lang.indexOf('_')+1);
}
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
Document doc = factory.newDocumentBuilder().newDocument();
Element rss = addNode(doc, doc, "rss");
addAttribute(doc, rss, "version", "2.0");
addAttribute(doc, rss, "xmlns:opensearch",
(String)NS_MAP.get("opensearch"));
addAttribute(doc, rss, "xmlns:atom", (String)NS_MAP.get("atom"));
addAttribute(doc, rss, "xmlns:photo", (String)NS_MAP.get("photo"));
addAttribute(doc, rss, "xmlns:media", (String)NS_MAP.get("media"));
Element channel = addNode(doc, rss, "channel");
if(kind.equals("album")){
addCategory(doc,channel,request);
}else if(kind.equals("photo")){
addPhoto(doc,channel,request);
}else{
response.getOutputStream().println("Invalid paramenter.");
return;
}
if(alt.equals("json")){
String value = null;
try {
value = org.json.XML.toJSONObject(doc.toString()).toString();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(value != null)
response.getOutputStream().print(value);
return;
}
// dump DOM tree
DOMSource source = new DOMSource(doc);
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.setOutputProperty("indent", "yes");
StreamResult result = new StreamResult(response.getOutputStream());
response.setContentType("text/xml");
transformer.transform(source, result);
} catch (javax.xml.parsers.ParserConfigurationException e) {
throw new ServletException(e);
} catch (javax.xml.transform.TransformerException e) {
throw new ServletException(e);
}
}
private static Element addNode(Document doc, Node parent, String name) {
Element child = doc.createElement(name);
parent.appendChild(child);
return child;
}
private static Element addNode(Document doc, Node parent,
String name, String text) {
Element child = doc.createElement(name);
child.appendChild(doc.createTextNode(getLegalXml(text)));
parent.appendChild(child);
return child;
}
private static Element addNode(Document doc, Node parent,
String ns, String name, String text) {
Element child = doc.createElementNS((String)NS_MAP.get(ns), ns+":"+name);
child.appendChild(doc.createTextNode(getLegalXml(text)));
parent.appendChild(child);
return child;
}
private static void addAttribute(Document doc, Element node,
String name, String value) {
Attr attribute = doc.createAttribute(name);
attribute.setValue(getLegalXml(value));
node.getAttributes().setNamedItem(attribute);
}
private static String parserText(final String text){
StringBuilder sb = new StringBuilder(text.length());
for(int i = 0 ; i < text.length() ;i++){
/*
& &
< ⁢
> >
" "
' '
*/
char s = text.charAt(i);
switch(s){
case 38: sb.append("&");
break;
case 60: sb.append("⁢");
break;
case 62: sb.append(">");
break;
case 34: sb.append(""");
break;
case 39: sb.append("'");
break;
default : sb.append(s);
}
}
return sb.toString();
}
/*
* Ensure string is legal xml.
* @param text String to verify.
* @return Passed <code>text</code> or a new string with illegal
* characters removed if any found in <code>text</code>.
* @see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char
*/
protected static String getLegalXml(final String text) {
if (text == null) {
return null;
}
StringBuffer buffer = null;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (!isLegalXml(c)) {
if (buffer == null) {
// Start up a buffer. Copy characters here from now on
// now we've found at least one bad character in original.
buffer = new StringBuffer(text.length());
buffer.append(text.substring(0, i));
}
} else {
if (buffer != null) {
buffer.append(c);
}
}
}
return (buffer != null)? buffer.toString(): text;
}
private static boolean isLegalXml(final char c) {
return c == 0x9 || c == 0xa || c == 0xd || (c >= 0x20 && c <= 0xd7ff)
|| (c >= 0xe000 && c <= 0xfffd) || (c >= 0x10000 && c <= 0x10ffff);
}
}