/*******************************************************************************
* Copyright (c) 2012 IBM Corporation.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
*
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*
* Keith Wells - initial API and implementation
* Sam Padgett - initial API and Implementation
* Jim Conallen - initial API and implementation
*
*******************************************************************************/
package org.eclipse.lyo.samples.sharepoint.services;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.lyo.samples.sharepoint.core.IConstants;
import org.eclipse.lyo.samples.sharepoint.l10n.Messages;
import org.eclipse.lyo.samples.sharepoint.services.ShareServiceException;
import org.eclipse.lyo.samples.sharepoint.store.OslcResource;
import org.eclipse.lyo.samples.sharepoint.store.ShareServerException;
import org.eclipse.lyo.samples.sharepoint.store.ShareStore;
import org.eclipse.lyo.samples.sharepoint.util.StringUtils;
import org.openrdf.rio.RDFFormat;
public abstract class ShareBaseService extends HttpServlet {
private static final long serialVersionUID = -8870677366709073238L;
protected ShareStore getStore() throws ShareServiceException {
try {
return ShareStore.getStore();
} catch (ShareServerException e) {
throw new ShareServiceException(e);
}
}
public String getBaseUrl() throws ShareServiceException{
return getStore().getUriBase();
}
public String getUserUri(String userId) throws ShareServiceException {
if( userId == null ) {
userId = IConstants.SHARE_UNKNOWN_USER_ID;
}
return this.getBaseUrl() + '/' + IConstants.SERVICE_USER + '/' + userId;
}
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(Messages.getString("ShareBaseService.NonHttpRequest")); //$NON-NLS-1$
}
try{
service(request, response);
response.setHeader(IConstants.HDR_OSLC_VERSION, IConstants.OSLC_VERSION);
} catch( ShareServiceException ex ) {
// return with an OSLC message style
response.setStatus(ex.getStatus());
response.setHeader(IConstants.HDR_OSLC_VERSION, IConstants.OSLC_VERSION);
response.setContentType(IConstants.CT_RDF_XML);
ShareError error = new ShareError(IConstants.SC_INTERNAL_ERROR, ex.getMessage() );
response.getWriter().write(error.toString());
} catch( Exception ex ) {
// return with an OSLC message style
response.setStatus(IConstants.SC_INTERNAL_ERROR);
response.setHeader(IConstants.HDR_OSLC_VERSION, IConstants.OSLC_VERSION);
response.setContentType(IConstants.CT_RDF_XML);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
ShareError error = new ShareError(IConstants.SC_INTERNAL_ERROR, sw.toString() );
response.getWriter().write(error.toString());
}
}
protected void checkConditionalHeaders(HttpServletRequest request, OslcResource resource) throws ShareServiceException {
String ifMatch = request.getHeader(IConstants.HDR_IF_MATCH);
String ifUnmodifiedSince = request.getHeader(IConstants.HDR_IF_UNMODIFIED_SINCE);
if( ifMatch == null && ifUnmodifiedSince == null ) {
throw new ShareServiceException(IConstants.SC_BAD,
Messages.getString("Resource.ConditionalHeaderRequired")); //$NON-NLS-1$
}
try{
if( ifMatch != null ) {
String eTag = resource.getETag();
if( !ifMatch.equals("*") && !ifMatch.equals(eTag) ) {
throw new ShareServiceException(IConstants.SC_PRECONDITION_FAILED, "ETag mismatch");
}
}
if( ifUnmodifiedSince != null ) {
Date unmodifiedSince = StringUtils.rfc2822(ifUnmodifiedSince);
Date modified = resource.getModified();
if( unmodifiedSince.after(modified) ) {
throw new ShareServiceException(IConstants.SC_PRECONDITION_FAILED, "Last modified after supplied If-Unmodified-Since value");
}
}
} catch (ParseException e) {
throw new ShareServiceException(IConstants.SC_PRECONDITION_FAILED, "Invalid If-Unmodified-Since Header");
} catch (Exception e ) {
throw new ShareServiceException(e);
}
}
protected boolean willAccept(String contentType, HttpServletRequest req) {
@SuppressWarnings("rawtypes")
Enumeration acceptHds = req.getHeaders(IConstants.HDR_ACCEPT);
while(acceptHds.hasMoreElements()) {
String acceptHdr = (String) acceptHds.nextElement();
// split up the individual content types
String[] hdrs = acceptHdr.split(",");
for (String acctHdrVal : hdrs) {
AcceptType acceptType = new AcceptType( acctHdrVal);
if( acceptType.equals(contentType) ) return true;
}
}
return false;
}
protected String acceptContentType(String[] prioritizedContentTypes, HttpServletRequest req) {
// simplified content negotiation, first get all accepted types, and order by qs
// then we walk through prioritized content types trying to find a match, in the
// order that the server prefers
List<AcceptType> acceptableTypes = new ArrayList<AcceptType>();
@SuppressWarnings("rawtypes")
Enumeration acceptHds = req.getHeaders(IConstants.HDR_ACCEPT);
while(acceptHds.hasMoreElements()) {
String acceptHdr = (String) acceptHds.nextElement();
// split up the individual content types
String[] hdrs = acceptHdr.split(",");
for (String acctHdrVal : hdrs) {
acceptableTypes.add( new AcceptType( acctHdrVal) );
}
// now sort by weight
Collections.sort(acceptableTypes);
// now find the most appropriate header
for (String contentType : prioritizedContentTypes) {
if( acceptableTypes.contains(new AcceptType(contentType) ) ) {
return contentType;
}
}
}
return null;
}
private class AcceptType implements Comparable<AcceptType> {
public String type;
public int weight;
public AcceptType(String typeExp) {
int pos = typeExp.indexOf(';');
if( pos > 0 ) {
this.type = typeExp.substring(0,pos).trim();
String qualifier = typeExp.substring(pos+1);
if( qualifier.startsWith("q=") ) {
try{
float w = Float.parseFloat(qualifier.substring(2)) * 1000;
this.weight = (int) w;
}catch( NumberFormatException e ) {
this.weight = 1000;
}
} else {
this.weight = 1000;
}
} else {
this.type = typeExp;
this.weight = new Integer(1000);
}
}
@Override
public int compareTo(AcceptType other) {
return ((AcceptType)other).weight - weight;
}
@Override
public boolean equals(Object obj) {
if( obj instanceof AcceptType ) {
AcceptType otherAcceptType = (AcceptType) obj;
// now we need to sort out wildcards
String[] otc = otherAcceptType.type.split("/");
String[] ttc = this.type.split("/");
boolean seg1 = compareSegment(otc[0], ttc[0]);
boolean seg2 = compareSegment(otc[1], ttc[1]);
return seg1 && seg2;
} else if( obj instanceof String ) {
String[] otc = ((String)obj).split("/");
String[] ttc = this.type.split("/");
boolean seg1 = compareSegment(otc[0], ttc[0]);
boolean seg2 = compareSegment(otc[1], ttc[1]);
return seg1 && seg2;
}
return false;
}
public boolean compareSegment(String s1, String s2 ) {
if( s1.equals("*") || s2.equals("*") ) {
return true;
}
return s1.equals(s2);
}
}
@SuppressWarnings({ })
protected RDFFormat acceptFormat(RDFFormat[] prioritizedFormats, HttpServletRequest req) {
@SuppressWarnings("rawtypes")
Enumeration acceptHds = req.getHeaders(IConstants.HDR_ACCEPT);
while(acceptHds.hasMoreElements()) {
String acceptHdr = (String) acceptHds.nextElement();
for (RDFFormat format : prioritizedFormats) {
List<String> mimeTypes = format.getMIMETypes();
for (String mimetype : mimeTypes) {
if( acceptHdr.indexOf(mimetype) >= 0 ) {
return format;
}
}
}
}
return null;
}
protected void reportError( int statusCode, String message, HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException{
req.setAttribute("statusCode", Integer.toString(statusCode)); //$NON-NLS-1$
req.setAttribute("message", StringUtils.forHtml(message) ); //$NON-NLS-1$
RequestDispatcher dispatcher =
req.getRequestDispatcher("/ori/web/error.jsp"); //$NON-NLS-1$
if (dispatcher != null) dispatcher.forward(req, resp);
}
}