/*******************************************************************************
*Copyright (c) 2009 Eucalyptus Systems, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, only version 3 of the License.
*
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Please contact Eucalyptus Systems, Inc., 130 Castilian
* Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
* if you need additional information or have any questions.
*
* This file may incorporate work covered under the following copyright and
* permission notice:
*
* Software License Agreement (BSD License)
*
* Copyright (c) 2008, Regents of the University of California
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
* THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
* LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
* SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
* IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
* BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
* THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
* OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
* WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
* ANY SUCH LICENSES OR RIGHTS.
*******************************************************************************/
package com.eucalyptus.ws.handlers;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.net.URLDecoder;
import java.text.ParseException;
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.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.axiom.om.OMElement;
import org.apache.commons.httpclient.util.DateUtil;
import org.apache.log4j.Logger;
import org.apache.tools.ant.util.DateUtils;
import org.apache.xml.dtm.ref.DTMNodeList;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.DownstreamMessageEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import com.eucalyptus.auth.principal.User;
import com.eucalyptus.auth.util.Hashes;
import com.eucalyptus.binding.Binding;
import com.eucalyptus.binding.BindingException;
import com.eucalyptus.binding.BindingManager;
import com.eucalyptus.binding.HoldMe;
import com.eucalyptus.binding.HttpEmbedded;
import com.eucalyptus.binding.HttpParameterMapping;
import com.eucalyptus.context.Context;
import com.eucalyptus.context.Contexts;
import com.eucalyptus.http.MappingHttpRequest;
import com.eucalyptus.http.MappingHttpResponse;
import com.eucalyptus.util.LogUtil;
import com.eucalyptus.util.StorageProperties;
import com.eucalyptus.util.WalrusProperties;
import com.eucalyptus.util.WalrusUtil;
import com.eucalyptus.ws.InvalidOperationException;
import com.eucalyptus.ws.handlers.WalrusAuthenticationHandler.SecurityParameter;
import com.eucalyptus.ws.util.WalrusBucketLogger;
import com.eucalyptus.ws.util.XMLParser;
import com.google.common.collect.Lists;
import edu.ucsb.eucalyptus.cloud.BucketLogData;
import edu.ucsb.eucalyptus.msgs.AccessControlListType;
import edu.ucsb.eucalyptus.msgs.AccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.CanonicalUserType;
import edu.ucsb.eucalyptus.msgs.EucalyptusErrorMessageType;
import edu.ucsb.eucalyptus.msgs.EucalyptusMessage;
import edu.ucsb.eucalyptus.msgs.Grant;
import edu.ucsb.eucalyptus.msgs.Grantee;
import edu.ucsb.eucalyptus.msgs.Group;
import edu.ucsb.eucalyptus.msgs.LoggingEnabled;
import edu.ucsb.eucalyptus.msgs.MetaDataEntry;
import edu.ucsb.eucalyptus.msgs.PutObjectResponseType;
import edu.ucsb.eucalyptus.msgs.TargetGrants;
import edu.ucsb.eucalyptus.msgs.WalrusDataGetRequestType;
import edu.ucsb.eucalyptus.msgs.WalrusDataRequestType;
import edu.ucsb.eucalyptus.msgs.WalrusRequestType;
import edu.ucsb.eucalyptus.msgs.PutObjectResponseType;
import edu.ucsb.eucalyptus.util.WalrusDataMessage;
import edu.ucsb.eucalyptus.util.WalrusDataMessenger;
import edu.ucsb.eucalyptus.util.WalrusDataQueue;
import groovy.lang.GroovyObject;
public class WalrusRESTBinding extends RestfulMarshallingHandler {
private static Logger LOG = Logger.getLogger( WalrusRESTBinding.class );
private static final String SERVICE = "service";
private static final String BUCKET = "bucket";
private static final String OBJECT = "object";
private static final Map<String, String> operationMap = populateOperationMap();
private static WalrusDataMessenger putMessenger;
public static final int DATA_MESSAGE_SIZE = 102400;
private String key;
private String randomKey;
private WalrusDataQueue<WalrusDataMessage> putQueue;
private static final int PUT_ENTRY_TIMEOUT = 500;
private static final int PUT_RETRY_COUNT = 30;
@Override
public void handleUpstream( final ChannelHandlerContext channelHandlerContext, final ChannelEvent channelEvent ) throws Exception {
LOG.trace( LogUtil.dumpObject( channelEvent ) );
if ( channelEvent instanceof MessageEvent ) {
final MessageEvent msgEvent = ( MessageEvent ) channelEvent;
try {
this.incomingMessage( channelHandlerContext, msgEvent );
} catch ( Throwable e ) {
LOG.error( e, e );
Channels.fireExceptionCaught( channelHandlerContext, e );
return;
}
} else if (channelEvent.toString().contains("DISCONNECTED") ||
channelEvent.toString().contains("CLOSED")) {
if(key != null && randomKey != null) {
putMessenger.removeQueue(key, randomKey);
putQueue = null;
}
}
channelHandlerContext.sendUpstream( channelEvent );
}
@Override
public void incomingMessage( ChannelHandlerContext ctx, MessageEvent event ) throws Exception {
if ( event.getMessage( ) instanceof MappingHttpRequest ) {
MappingHttpRequest httpRequest = ( MappingHttpRequest ) event.getMessage( );
namespace = "http://s3.amazonaws.com/doc/" + WalrusProperties.NAMESPACE_VERSION;
// TODO: get real user data here too
EucalyptusMessage msg = (EucalyptusMessage) this.bind( "admin", true, httpRequest );
httpRequest.setMessage( msg );
if(msg instanceof WalrusDataGetRequestType) {
WalrusDataGetRequestType getObject = (WalrusDataGetRequestType) msg;
getObject.setChannel(ctx.getChannel());
}
if(msg instanceof WalrusDataRequestType) {
String expect = httpRequest.getHeader(HttpHeaders.Names.EXPECT);
if(expect != null) {
if(expect.equals("100-continue")) {
HttpResponse response = new DefaultHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE );
DownstreamMessageEvent newEvent = new DownstreamMessageEvent( ctx.getChannel( ), event.getFuture(), response, null );
ctx.sendDownstream( newEvent );
}
}
}
} else if(event.getMessage() instanceof HttpChunk) {
if(putQueue != null) {
HttpChunk httpChunk = (HttpChunk) event.getMessage();
handleHttpChunk(httpChunk);
}
}
}
@Override
public void outgoingMessage( ChannelHandlerContext ctx, MessageEvent event ) throws Exception {
if ( event.getMessage( ) instanceof MappingHttpResponse ) {
MappingHttpResponse httpResponse = ( MappingHttpResponse ) event.getMessage( );
EucalyptusMessage msg = (EucalyptusMessage) httpResponse.getMessage( );
Binding binding;
if(!(msg instanceof EucalyptusErrorMessageType)) {
binding = BindingManager.getBinding( BindingManager.sanitizeNamespace( namespace ) );
if(putQueue != null) {
putQueue = null;
}
} else {
binding = BindingManager.getBinding( BindingManager.sanitizeNamespace( "http://msgs.eucalyptus.com" ) );
if(putQueue != null) {
putQueue = null;
}
}
if(msg != null) {
OMElement omMsg = binding.toOM( msg );
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
HoldMe.canHas.lock();
try {
omMsg.serialize( byteOut );
} finally {
HoldMe.canHas.unlock();
}
byte[] req = byteOut.toByteArray();
ChannelBuffer buffer = ChannelBuffers.copiedBuffer( req );
httpResponse.addHeader( HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buffer.readableBytes() ) );
httpResponse.addHeader( HttpHeaders.Names.CONTENT_TYPE, "application/xml" );
httpResponse.setContent( buffer );
}
}
}
private static Map<String, String> populateOperationMap() {
Map<String, String> newMap = new HashMap<String, String>();
//Service operations
newMap.put(SERVICE + WalrusProperties.HTTPVerb.GET.toString(), "ListAllMyBuckets");
//Bucket operations
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.acl.toString(), "GetBucketAccessControlPolicy");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.PUT.toString() + WalrusProperties.OperationParameter.acl.toString(), "SetRESTBucketAccessControlPolicy");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString(), "ListBucket");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.prefix.toString(), "ListBucket");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.maxkeys.toString(), "ListBucket");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.marker.toString(), "ListBucket");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.delimiter.toString(), "ListBucket");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.PUT.toString(), "CreateBucket");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.DELETE.toString(), "DeleteBucket");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.location.toString(), "GetBucketLocation");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.logging.toString(), "GetBucketLoggingStatus");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.PUT.toString() + WalrusProperties.OperationParameter.logging.toString(), "SetBucketLoggingStatus");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.versions.toString(), "ListVersions");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.versioning.toString(), "GetBucketVersioningStatus");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.PUT.toString() + WalrusProperties.OperationParameter.versioning.toString(), "SetBucketVersioningStatus");
//Object operations
newMap.put(OBJECT + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.acl.toString(), "GetObjectAccessControlPolicy");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.PUT.toString() + WalrusProperties.OperationParameter.acl.toString(), "SetRESTObjectAccessControlPolicy");
newMap.put(BUCKET + WalrusProperties.HTTPVerb.POST.toString(), "PostObject");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.PUT.toString(), "PutObject");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.PUT.toString() + WalrusProperties.COPY_SOURCE.toString(), "CopyObject");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.GET.toString(), "GetObject");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.GET.toString() + WalrusProperties.OperationParameter.torrent.toString(), "GetObject");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.DELETE.toString(), "DeleteObject");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.HEAD.toString(), "GetObject");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.GET.toString() + "extended", "GetObjectExtended");
newMap.put(OBJECT + WalrusProperties.HTTPVerb.DELETE.toString() + WalrusProperties.OperationParameter.versionId.toString().toLowerCase(), "DeleteVersion");
return newMap;
}
@Override
public Object bind( final String userId, final boolean admin, final MappingHttpRequest httpRequest ) throws Exception {
String servicePath = httpRequest.getServicePath();
Map bindingArguments = new HashMap();
final String operationName = getOperation(httpRequest, bindingArguments);
if(operationName == null)
throw new InvalidOperationException("Could not determine operation name for " + servicePath);
Map<String, String> params = httpRequest.getParameters();
OMElement msg;
EucalyptusMessage eucaMsg;
Map<String, String> fieldMap;
Class targetType;
try
{
//:: try to create the target class :://
targetType = ClassLoader.getSystemClassLoader().loadClass( "edu.ucsb.eucalyptus.msgs.".concat( operationName ).concat( "Type" ) );
//:: get the map of parameters to fields :://
fieldMap = this.buildFieldMap( targetType );
//:: get an instance of the message :://
eucaMsg = (EucalyptusMessage) targetType.newInstance();
}
catch ( Exception e )
{
throw new BindingException( "Failed to construct message of type " + operationName );
}
addLogData(eucaMsg, bindingArguments);
//TODO: Refactor this to be more general
List<String> failedMappings = populateObject( eucaMsg, fieldMap, params);
populateObjectFromBindingMap(eucaMsg, fieldMap, httpRequest, bindingArguments);
User user = Contexts.lookup( httpRequest.getCorrelationId( ) ).getUser();
setRequiredParams (eucaMsg, user);
if ( !failedMappings.isEmpty() || !params.isEmpty() )
{
StringBuilder errMsg = new StringBuilder( "Failed to bind the following fields:\n" );
for ( String f : failedMappings )
errMsg.append( f ).append( '\n' );
for ( Map.Entry<String, String> f : params.entrySet() )
errMsg.append( f.getKey() ).append( " = " ).append( f.getValue() ).append( '\n' );
throw new BindingException( errMsg.toString() );
}
LOG.info(eucaMsg.toString());
try
{
Binding binding = BindingManager.getBinding( BindingManager.sanitizeNamespace( "http://msgs.eucalyptus.com" ) );
msg = binding.toOM( eucaMsg );
}
catch ( RuntimeException e )
{
throw new BindingException( "Failed to build a valid message: " + e.getMessage() );
}
return eucaMsg;
}
private void addLogData(EucalyptusMessage eucaMsg,
Map bindingArguments) {
if(eucaMsg instanceof WalrusRequestType) {
String operation = (String) bindingArguments.remove("Operation");
if(operation != null) {
WalrusRequestType request = (WalrusRequestType) eucaMsg;
BucketLogData logData = WalrusBucketLogger.getInstance().makeLogEntry(UUID.randomUUID().toString());
logData.setOperation("REST." + operation);
request.setLogData(logData);
}
}
}
private void setRequiredParams(final GroovyObject msg, User user) {
if(user != null) {
msg.setProperty("accessKeyID", user.getQueryId());
}
msg.setProperty("timeStamp", new Date());
}
private String getOperation(MappingHttpRequest httpRequest, Map operationParams) throws BindingException {
String[] target = null;
String path = getOperationPath(httpRequest);
boolean walrusInternalOperation = false;
String targetHost = httpRequest.getHeader(HttpHeaders.Names.HOST);
if(targetHost.contains(".walrus")) {
String bucket = targetHost.substring(0, targetHost.indexOf(".walrus"));
path = "/" + bucket + path;
}
if(path.length() > 0) {
target = WalrusUtil.getTarget(path);
}
String verb = httpRequest.getMethod().getName();
String operationKey = "";
Map<String, String> params = httpRequest.getParameters();
String operationName = null;
long contentLength = 0;
String contentLengthString = httpRequest.getHeader(WalrusProperties.CONTENT_LEN);
if(contentLengthString != null) {
contentLength = Long.parseLong(contentLengthString);
}
if(httpRequest.containsHeader(StorageProperties.EUCALYPTUS_OPERATION)) {
String value = httpRequest.getHeader(StorageProperties.EUCALYPTUS_OPERATION);
for(WalrusProperties.WalrusInternalOperations operation: WalrusProperties.WalrusInternalOperations.values()) {
if(value.toLowerCase().equals(operation.toString().toLowerCase())) {
operationName = operation.toString();
walrusInternalOperation = true;
break;
}
}
if(!walrusInternalOperation) {
for(WalrusProperties.StorageOperations operation: WalrusProperties.StorageOperations.values()) {
if(value.toLowerCase().equals(operation.toString().toLowerCase())) {
operationName = operation.toString();
walrusInternalOperation = true;
if(httpRequest.containsHeader(StorageProperties.StorageParameters.EucaSnapSize.toString())) {
operationParams.put("SnapshotSize", httpRequest.getAndRemoveHeader(StorageProperties.StorageParameters.EucaSnapSize.toString()));
}
break;
}
}
}
}
if(target == null) {
//target = service
operationKey = SERVICE + verb;
} else if(target.length < 2) {
//target = bucket
if(!target[0].equals("")) {
operationKey = BUCKET + verb;
operationParams.put("Bucket", target[0]);
operationParams.put("Operation", verb.toUpperCase() + "." + "BUCKET");
if(verb.equals(WalrusProperties.HTTPVerb.POST.toString())) {
//TODO: handle POST.
Map formFields = httpRequest.getFormFields();
String objectKey = null;
String file = (String) formFields.get(WalrusProperties.FormField.file.toString());
String authenticationHeader = "";
if(formFields.containsKey(WalrusProperties.FormField.key.toString())) {
objectKey = (String) formFields.get(WalrusProperties.FormField.key.toString());
objectKey = objectKey.replaceAll("\\$\\{filename\\}", file);
operationParams.put("Key", objectKey);
}
if(formFields.containsKey(WalrusProperties.FormField.acl.toString())) {
String acl = (String) formFields.get(WalrusProperties.FormField.acl.toString());
httpRequest.addHeader(WalrusProperties.AMZ_ACL, acl);
}
if(formFields.containsKey(WalrusProperties.FormField.redirect.toString())) {
String successActionRedirect = (String) formFields.get(WalrusProperties.FormField.redirect.toString());
operationParams.put("SuccessActionRedirect", successActionRedirect);
}
if(formFields.containsKey(WalrusProperties.FormField.success_action_redirect.toString())) {
String successActionRedirect = (String) formFields.get(WalrusProperties.FormField.success_action_redirect.toString());
operationParams.put("SuccessActionRedirect", successActionRedirect);
}
if(formFields.containsKey(WalrusProperties.FormField.success_action_status.toString())) {
Integer successActionStatus = Integer.parseInt((String)formFields.get(WalrusProperties.FormField.success_action_status.toString()));
if(successActionStatus == 200 || successActionStatus == 201)
operationParams.put("SuccessActionStatus", successActionStatus);
else
operationParams.put("SuccessActionStatus", 204);
} else {
operationParams.put("SuccessActionStatus", 204);
}
if(formFields.containsKey(WalrusProperties.CONTENT_TYPE)) {
operationParams.put("ContentType", formFields.get(WalrusProperties.CONTENT_TYPE));
}
key = target[0] + "." + objectKey;
randomKey = key + "." + Hashes.getRandom(10);
if(contentLengthString != null)
operationParams.put("ContentLength", (new Long(contentLength).toString()));
operationParams.put(WalrusProperties.Headers.RandomKey.toString(), randomKey);
putQueue = getWriteMessenger().interruptAllAndGetQueue(key, randomKey);
handleFirstChunk(httpRequest, (ChannelBuffer)formFields.get(WalrusProperties.IGNORE_PREFIX + "FirstDataChunk"), contentLength);
} else if(WalrusProperties.HTTPVerb.PUT.toString().equals(verb)) {
if(params.containsKey(WalrusProperties.OperationParameter.logging.toString())) {
//read logging params
getTargetBucketParams(operationParams, httpRequest);
} else if(params.containsKey(WalrusProperties.OperationParameter.versioning.toString())) {
getVersioningStatus(operationParams, httpRequest);
}
}
} else {
operationKey = SERVICE + verb;
}
} else {
//target = object
operationKey = OBJECT + verb;
String objectKey="";
String splitOn = "";
for(int i = 1; i < target.length; ++i) {
objectKey += splitOn + target[i];
splitOn = "/";
}
try {
objectKey = WalrusUtil.URLdecode(objectKey);
} catch (UnsupportedEncodingException e) {
throw new BindingException("Unable to get key: " + e.getMessage());
}
operationParams.put("Bucket", target[0]);
operationParams.put("Key", objectKey);
operationParams.put("Operation", verb.toUpperCase() + "." + "OBJECT");
if(!params.containsKey(WalrusProperties.OperationParameter.acl.toString())) {
if (verb.equals(WalrusProperties.HTTPVerb.PUT.toString())) {
if(httpRequest.containsHeader(WalrusProperties.COPY_SOURCE.toString())) {
String copySource = httpRequest.getHeader(WalrusProperties.COPY_SOURCE.toString());
String[] sourceParts = copySource.split("\\?");
if(sourceParts.length > 1) {
operationParams.put("SourceVersionId", sourceParts[1].replaceFirst("versionId=", "").trim());
}
copySource = sourceParts[0];
String[] sourceTarget = WalrusUtil.getTarget(copySource);
String sourceObjectKey = "";
String sourceSplitOn = "";
if(sourceTarget.length > 1) {
for(int i = 1; i < sourceTarget.length; ++i) {
sourceObjectKey += sourceSplitOn + sourceTarget[i];
sourceSplitOn = "/";
}
try {
sourceObjectKey = WalrusUtil.URLdecode(sourceObjectKey);
} catch (UnsupportedEncodingException e) {
throw new BindingException("Unable to get source key: " + e.getMessage());
}
operationParams.put("SourceBucket", sourceTarget[0]);
operationParams.put("SourceObject", sourceObjectKey);
operationParams.put("DestinationBucket", operationParams.remove("Bucket"));
operationParams.put("DestinationObject", operationParams.remove("Key"));
String metaDataDirective = httpRequest.getHeader(WalrusProperties.METADATA_DIRECTIVE.toString());
if(metaDataDirective != null) {
operationParams.put("MetadataDirective", metaDataDirective);
}
AccessControlListType accessControlList;
if(contentLength > 0) {
accessControlList = null;
accessControlList = getAccessControlList(httpRequest);
} else {
accessControlList = new AccessControlListType();
}
operationParams.put("AccessControlList", accessControlList);
operationKey += WalrusProperties.COPY_SOURCE.toString();
Set<String> headerNames = httpRequest.getHeaderNames();
for(String key : headerNames) {
for(WalrusProperties.CopyHeaders header: WalrusProperties.CopyHeaders.values()) {
if(key.replaceAll("-", "").equals(header.toString().toLowerCase())) {
String value = httpRequest.getHeader(key);
parseExtendedHeaders(operationParams, header.toString(), value);
}
}
}
} else {
throw new BindingException("Malformed COPY request");
}
} else {
//handle PUTs
key = target[0] + "." + objectKey;
randomKey = key + "." + Hashes.getRandom(10);
String contentType = httpRequest.getHeader(WalrusProperties.CONTENT_TYPE);
if(contentType != null)
operationParams.put("ContentType", contentType);
String contentDisposition = httpRequest.getHeader("Content-Disposition");
if(contentDisposition != null)
operationParams.put("ContentDisposition", contentDisposition);
if(contentLengthString != null)
operationParams.put("ContentLength", (new Long(contentLength).toString()));
operationParams.put(WalrusProperties.Headers.RandomKey.toString(), randomKey);
putQueue = getWriteMessenger().interruptAllAndGetQueue(key, randomKey);
handleFirstChunk(httpRequest, contentLength);
}
} else if(verb.equals(WalrusProperties.HTTPVerb.GET.toString())) {
if(!walrusInternalOperation) {
if(params.containsKey("torrent")) {
operationParams.put("GetTorrent", Boolean.TRUE);
} else {
operationParams.put("GetData", Boolean.TRUE);
operationParams.put("InlineData", Boolean.FALSE);
operationParams.put("GetMetaData", Boolean.TRUE);
}
Set<String> headerNames = httpRequest.getHeaderNames();
boolean isExtendedGet = false;
for(String key : headerNames) {
for(WalrusProperties.ExtendedGetHeaders header: WalrusProperties.ExtendedGetHeaders.values()) {
if(key.replaceAll("-", "").equals(header.toString())) {
String value = httpRequest.getHeader(key);
isExtendedGet = true;
parseExtendedHeaders(operationParams, header.toString(), value);
}
}
}
if(isExtendedGet) {
operationKey += "extended";
//only supported through SOAP
operationParams.put("ReturnCompleteObjectOnConditionFailure", Boolean.FALSE);
}
}
if(params.containsKey(WalrusProperties.GetOptionalParameters.IsCompressed.toString())) {
Boolean isCompressed = Boolean.parseBoolean(params.remove(WalrusProperties.GetOptionalParameters.IsCompressed.toString()));
operationParams.put("IsCompressed", isCompressed);
}
} else if(verb.equals(WalrusProperties.HTTPVerb.HEAD.toString())) {
if(!walrusInternalOperation) {
operationParams.put("GetData", Boolean.FALSE);
operationParams.put("InlineData", Boolean.FALSE);
operationParams.put("GetMetaData", Boolean.TRUE);
}
}
}
if(params.containsKey(WalrusProperties.OperationParameter.versionId.toString())) {
if(!verb.equals(WalrusProperties.HTTPVerb.DELETE.toString()))
operationParams.put("VersionId", params.remove(WalrusProperties.OperationParameter.versionId.toString()));
}
}
if (verb.equals(WalrusProperties.HTTPVerb.PUT.toString()) && params.containsKey(WalrusProperties.OperationParameter.acl.toString())) {
operationParams.put("AccessControlPolicy", getAccessControlPolicy(httpRequest));
}
ArrayList paramsToRemove = new ArrayList();
boolean addMore = true;
Iterator iterator = params.keySet().iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
String keyString = key.toString().toLowerCase();
boolean dontIncludeParam = false;
for(WalrusAuthenticationHandler.SecurityParameter securityParam : WalrusAuthenticationHandler.SecurityParameter.values()) {
if(keyString.equals(securityParam.toString().toLowerCase())) {
dontIncludeParam = true;
break;
}
}
if(dontIncludeParam)
continue;
String value = params.get(key);
if(value != null) {
String[] keyStringParts = keyString.split("-");
if(keyStringParts.length > 1) {
keyString = "";
for(int i=0; i < keyStringParts.length; ++i) {
keyString += toUpperFirst(keyStringParts[i]);
}
} else {
keyString = toUpperFirst(keyString);
}
operationParams.put(keyString, value);
}
if(addMore) {
//just add the first one to the key
operationKey += keyString.toLowerCase();
addMore = false;
}
paramsToRemove.add(key);
}
for(Object key : paramsToRemove) {
params.remove(key);
}
if(!walrusInternalOperation) {
operationName = operationMap.get(operationKey);
}
if("CreateBucket".equals(operationName)) {
String locationConstraint = getLocationConstraint(httpRequest);
if(locationConstraint != null)
operationParams.put("LocationConstraint", locationConstraint);
}
return operationName;
}
private void getTargetBucketParams(Map operationParams,
MappingHttpRequest httpRequest) throws BindingException {
String message = getMessageString(httpRequest);
if(message.length() > 0) {
try {
XMLParser xmlParser = new XMLParser(message);
String targetBucket = xmlParser.getValue("//TargetBucket");
if(targetBucket == null || targetBucket.length() == 0)
return;
String targetPrefix = xmlParser.getValue("//TargetPrefix");
ArrayList<Grant> grants = new ArrayList<Grant>();
List<String> permissions = xmlParser.getValues("//TargetGrants/Grant/Permission");
if(permissions == null)
throw new BindingException("malformed access control list");
DTMNodeList grantees = xmlParser.getNodes("//TargetGrants/Grant/Grantee");
if(grantees == null)
throw new BindingException("malformed access control list");
for(int i = 0 ; i < grantees.getLength() ; ++i) {
String id = xmlParser.getValue(grantees.item(i), "ID");
if(id.length() > 0) {
String canonicalUserName = xmlParser.getValue(grantees.item(i), "DisplayName");
Grant grant = new Grant();
Grantee grantee = new Grantee();
grantee.setCanonicalUser(new CanonicalUserType(id, canonicalUserName));
grant.setGrantee(grantee);
grant.setPermission(permissions.get(i));
grants.add(grant);
} else {
String groupUri = xmlParser.getValue(grantees.item(i), "URI");
if(groupUri.length() == 0)
throw new BindingException("malformed access control list");
Grant grant = new Grant();
Grantee grantee = new Grantee();
grantee.setGroup(new Group(groupUri));
grant.setGrantee(grantee);
grant.setPermission(permissions.get(i));
grants.add(grant);
}
}
TargetGrants targetGrants = new TargetGrants(grants);
LoggingEnabled loggingEnabled = new LoggingEnabled(targetBucket, targetPrefix, new TargetGrants(grants));
operationParams.put("LoggingEnabled", loggingEnabled);
} catch(Exception ex) {
LOG.warn(ex);
throw new BindingException("Unable to parse logging configuration " + ex.getMessage());
}
}
}
private void getVersioningStatus(Map operationParams,
MappingHttpRequest httpRequest) throws BindingException {
String message = getMessageString(httpRequest);
if(message.length() > 0) {
try {
XMLParser xmlParser = new XMLParser(message);
String status = xmlParser.getValue("//Status");
if(status == null || status.length() == 0)
return;
operationParams.put("VersioningStatus", status);
} catch(Exception ex) {
LOG.warn(ex);
throw new BindingException("Unable to parse versioning status " + ex.getMessage());
}
}
}
private void parseExtendedHeaders(Map operationParams, String headerString, String value) throws BindingException {
if(headerString.equals(WalrusProperties.ExtendedGetHeaders.Range.toString())) {
String prefix = "bytes=";
assert(value.startsWith(prefix));
value = value.substring(prefix.length());
String[]values = value.split("-");
assert(values.length == 2);
if(values[0].equals("")) {
operationParams.put(WalrusProperties.ExtendedHeaderRangeTypes.ByteRangeStart.toString(), new Long(0));
} else {
operationParams.put(WalrusProperties.ExtendedHeaderRangeTypes.ByteRangeStart.toString(), Long.parseLong(values[0]));
}
assert(!values[1].equals(""));
operationParams.put(WalrusProperties.ExtendedHeaderRangeTypes.ByteRangeEnd.toString(), Long.parseLong(values[1]));
} else if(WalrusProperties.ExtendedHeaderDateTypes.contains(headerString)) {
try {
List<String> dateFormats = new ArrayList<String>();
dateFormats.add(DateUtil.PATTERN_RFC1123);
operationParams.put(headerString, DateUtil.parseDate(value, dateFormats));
} catch(Exception ex) {
try {
operationParams.put(headerString, DateUtils.parseIso8601DateTime(value));
} catch (ParseException e) {
LOG.error(e);
throw new BindingException(e);
}
}
} else {
operationParams.put(headerString, value);
}
}
private AccessControlPolicyType getAccessControlPolicy(MappingHttpRequest httpRequest) throws BindingException {
AccessControlPolicyType accessControlPolicy = new AccessControlPolicyType();
AccessControlListType accessControlList = new AccessControlListType();
ArrayList<Grant> grants = new ArrayList<Grant>();
try {
String aclString = getMessageString(httpRequest);
if(aclString.length() > 0) {
XMLParser xmlParser = new XMLParser(aclString);
String ownerId = xmlParser.getValue("//Owner/ID");
String displayName = xmlParser.getValue("//Owner/DisplayName");
CanonicalUserType canonicalUser = new CanonicalUserType(ownerId, displayName);
accessControlPolicy.setOwner(canonicalUser);
List<String> permissions = xmlParser.getValues("//AccessControlList/Grant/Permission");
if(permissions == null)
throw new BindingException("malformed access control list");
DTMNodeList grantees = xmlParser.getNodes("//AccessControlList/Grant/Grantee");
if(grantees == null)
throw new BindingException("malformed access control list");
for(int i = 0 ; i < grantees.getLength() ; ++i) {
String id = xmlParser.getValue(grantees.item(i), "ID");
if(id.length() > 0) {
String canonicalUserName = xmlParser.getValue(grantees.item(i), "DisplayName");
Grant grant = new Grant();
Grantee grantee = new Grantee();
grantee.setCanonicalUser(new CanonicalUserType(id, canonicalUserName));
grant.setGrantee(grantee);
grant.setPermission(permissions.get(i));
grants.add(grant);
} else {
String groupUri = xmlParser.getValue(grantees.item(i), "URI");
if(groupUri.length() == 0)
throw new BindingException("malformed access control list");
Grant grant = new Grant();
Grantee grantee = new Grantee();
grantee.setGroup(new Group(groupUri));
grant.setGrantee(grantee);
grant.setPermission(permissions.get(i));
grants.add(grant);
}
}
}
} catch(Exception ex) {
LOG.warn(ex);
throw new BindingException("Unable to parse access control policy " + ex.getMessage());
}
accessControlList.setGrants(grants);
accessControlPolicy.setAccessControlList(accessControlList);
return accessControlPolicy;
}
private AccessControlListType getAccessControlList(MappingHttpRequest httpRequest) throws BindingException {
AccessControlListType accessControlList = new AccessControlListType();
ArrayList<Grant> grants = new ArrayList<Grant>();
try {
String aclString = getMessageString(httpRequest);
if(aclString.length() > 0) {
XMLParser xmlParser = new XMLParser(aclString);
String ownerId = xmlParser.getValue("//Owner/ID");
String displayName = xmlParser.getValue("//Owner/DisplayName");
List<String> permissions = xmlParser.getValues("/AccessControlList/Grant/Permission");
if(permissions == null)
throw new BindingException("malformed access control list");
DTMNodeList grantees = xmlParser.getNodes("/AccessControlList/Grant/Grantee");
if(grantees == null)
throw new BindingException("malformed access control list");
for(int i = 0 ; i < grantees.getLength() ; ++i) {
String canonicalUserName = xmlParser.getValue(grantees.item(i), "DisplayName");
if(canonicalUserName.length() > 0) {
String id = xmlParser.getValue(grantees.item(i), "ID");
Grant grant = new Grant();
Grantee grantee = new Grantee();
grantee.setCanonicalUser(new CanonicalUserType(id, canonicalUserName));
grant.setGrantee(grantee);
grant.setPermission(permissions.get(i));
grants.add(grant);
} else {
String groupUri = xmlParser.getValue(grantees.item(i), "URI");
if(groupUri.length() == 0)
throw new BindingException("malformed access control list");
Grant grant = new Grant();
Grantee grantee = new Grantee();
grantee.setGroup(new Group(groupUri));
grant.setGrantee(grantee);
grant.setPermission(permissions.get(i));
grants.add(grant);
}
}
}
} catch(Exception ex) {
LOG.warn(ex);
throw new BindingException("Unable to parse access control list " + ex.getMessage());
}
accessControlList.setGrants(grants);
return accessControlList;
}
private String getOperationPath(MappingHttpRequest httpRequest) {
return httpRequest.getServicePath().replaceAll(WalrusProperties.walrusServicePath, "");
}
private String getLocationConstraint(MappingHttpRequest httpRequest) throws BindingException {
String locationConstraint = null;
try {
String bucketConfiguration = getMessageString(httpRequest);
if(bucketConfiguration.length() > 0) {
XMLParser xmlParser = new XMLParser(bucketConfiguration);
locationConstraint = xmlParser.getValue("/CreateBucketConfiguration/LocationConstraint");
}
} catch(Exception ex) {
LOG.warn(ex);
throw new BindingException(ex.getMessage());
}
return locationConstraint;
}
private List<String> populateObject( final GroovyObject obj, final Map<String, String> paramFieldMap, final Map<String, String> params ) {
List<String> failedMappings = new ArrayList<String>( );
for ( Map.Entry<String, String> e : paramFieldMap.entrySet( ) ) {
try {
if ( obj.getClass( ).getDeclaredField( e.getValue( ) ).getType( ).equals( ArrayList.class ) ) failedMappings.addAll( populateObjectList( obj, e, params, params.size( ) ) );
} catch ( NoSuchFieldException e1 ) {
failedMappings.add( e.getKey( ) );
}
}
for ( Map.Entry<String, String> e : paramFieldMap.entrySet( ) ) {
if ( params.containsKey( e.getKey( ) ) && !populateObjectField( obj, e, params ) ) failedMappings.add( e.getKey( ) );
}
return failedMappings;
}
private void populateObjectFromBindingMap( final GroovyObject obj, final Map<String, String> paramFieldMap, final MappingHttpRequest httpRequest, final Map bindingMap)
{
//process headers
String aclString = httpRequest.getAndRemoveHeader(WalrusProperties.AMZ_ACL);
if (aclString != null) {
addAccessControlList(obj, paramFieldMap, bindingMap, aclString);
}
//add meta data
String metaDataString = paramFieldMap.remove("MetaData");
if(metaDataString != null) {
Set<String> headerNames = httpRequest.getHeaderNames();
ArrayList<MetaDataEntry> metaData = new ArrayList<MetaDataEntry>();
for(String key : headerNames) {
if(key.toLowerCase().startsWith(WalrusProperties.AMZ_META_HEADER_PREFIX)) {
MetaDataEntry metaDataEntry = new MetaDataEntry();
metaDataEntry.setName(key.substring(WalrusProperties.AMZ_META_HEADER_PREFIX.length()));
metaDataEntry.setValue(httpRequest.getHeader(key));
metaData.add(metaDataEntry);
}
}
obj.setProperty(metaDataString, metaData);
}
//populate from binding map (required params)
Iterator bindingMapIterator = bindingMap.keySet().iterator();
while(bindingMapIterator.hasNext()) {
String key = (String) bindingMapIterator.next();
obj.setProperty(key.substring(0, 1).toLowerCase().concat(key.substring(1)), bindingMap.get(key));
}
}
private boolean populateObjectField( final GroovyObject obj, final Map.Entry<String, String> paramFieldPair, final Map<String, String> params ) {
try {
Class declaredType = obj.getClass( ).getDeclaredField( paramFieldPair.getValue( ) ).getType( );
if ( declaredType.equals( String.class ) ) obj.setProperty( paramFieldPair.getValue( ), params.remove( paramFieldPair.getKey( ) ) );
else if ( declaredType.getName( ).equals( "int" ) ) obj.setProperty( paramFieldPair.getValue( ), Integer.parseInt( params.remove( paramFieldPair.getKey( ) ) ) );
else if ( declaredType.equals( Integer.class ) ) obj.setProperty( paramFieldPair.getValue( ), new Integer( params.remove( paramFieldPair.getKey( ) ) ) );
else if ( declaredType.getName( ).equals( "boolean" ) ) obj.setProperty( paramFieldPair.getValue( ), Boolean.parseBoolean( params.remove( paramFieldPair.getKey( ) ) ) );
else if ( declaredType.equals( Boolean.class ) ) obj.setProperty( paramFieldPair.getValue( ), new Boolean( params.remove( paramFieldPair.getKey( ) ) ) );
else if ( declaredType.getName( ).equals( "long" ) ) obj.setProperty( paramFieldPair.getValue( ), Long.parseLong( params.remove( paramFieldPair.getKey( ) ) ) );
else if ( declaredType.equals( Long.class ) ) obj.setProperty( paramFieldPair.getValue( ), new Long( params.remove( paramFieldPair.getKey( ) ) ) );
else return false;
return true;
} catch ( Exception e1 ) {
return false;
}
}
private List<String> populateObjectList( final GroovyObject obj, final Map.Entry<String, String> paramFieldPair, final Map<String, String> params, final int paramSize ) {
List<String> failedMappings = new ArrayList<String>( );
try {
Field declaredField = obj.getClass( ).getDeclaredField( paramFieldPair.getValue( ) );
ArrayList theList = ( ArrayList ) obj.getProperty( paramFieldPair.getValue( ) );
Class genericType = ( Class ) ( ( ParameterizedType ) declaredField.getGenericType( ) ).getActualTypeArguments( )[0];
// :: simple case: FieldName.# :://
if ( String.class.equals( genericType ) ) {
if ( params.containsKey( paramFieldPair.getKey( ) ) ) {
theList.add( params.remove( paramFieldPair.getKey( ) ) );
} else {
List<String> keys = Lists.newArrayList( params.keySet( ) );
for ( String k : keys ) {
if ( k.matches( paramFieldPair.getKey( ) + "\\.\\d*" ) ) {
theList.add( params.remove( k ) );
}
}
}
} else if ( declaredField.isAnnotationPresent( HttpEmbedded.class ) ) {
HttpEmbedded annoteEmbedded = ( HttpEmbedded ) declaredField.getAnnotation( HttpEmbedded.class );
// :: build the parameter map and call populate object recursively :://
if ( annoteEmbedded.multiple( ) ) {
String prefix = paramFieldPair.getKey( );
List<String> embeddedListFieldNames = new ArrayList<String>( );
for ( String actualParameterName : params.keySet( ) )
if ( actualParameterName.matches( prefix + ".1.*" ) ) embeddedListFieldNames.add( actualParameterName.replaceAll( prefix + ".1.", "" ) );
for ( int i = 0; i < paramSize + 1; i++ ) {
boolean foundAll = true;
Map<String, String> embeddedParams = new HashMap<String, String>( );
for ( String fieldName : embeddedListFieldNames ) {
String paramName = prefix + "." + i + "." + fieldName;
if ( !params.containsKey( paramName ) ) {
failedMappings.add( "Mismatched embedded field: " + paramName );
foundAll = false;
} else embeddedParams.put( fieldName, params.get( paramName ) );
}
if ( foundAll ) failedMappings.addAll( populateEmbedded( genericType, embeddedParams, theList ) );
else break;
}
} else failedMappings.addAll( populateEmbedded( genericType, params, theList ) );
}
} catch ( Exception e1 ) {
failedMappings.add( paramFieldPair.getKey( ) );
}
return failedMappings;
}
private List<String> populateEmbedded( final Class genericType, final Map<String, String> params, final ArrayList theList ) throws InstantiationException, IllegalAccessException {
GroovyObject embedded = ( GroovyObject ) genericType.newInstance( );
Map<String, String> embeddedFields = buildFieldMap( genericType );
int startSize = params.size( );
List<String> embeddedFailures = populateObject( embedded, embeddedFields, params );
if ( embeddedFailures.isEmpty( ) && !( params.size( ) - startSize == 0 ) ) theList.add( embedded );
return embeddedFailures;
}
private Map<String, String> buildFieldMap( final Class targetType ) {
Map<String, String> fieldMap = new HashMap<String, String>( );
Field[] fields = targetType.getDeclaredFields( );
for ( Field f : fields )
if ( Modifier.isStatic( f.getModifiers( ) ) ) continue;
else if ( f.isAnnotationPresent( HttpParameterMapping.class ) ) {
fieldMap.put( f.getAnnotation( HttpParameterMapping.class ).parameter( ), f.getName( ) );
fieldMap.put( f.getName( ).substring( 0, 1 ).toUpperCase( ).concat( f.getName( ).substring( 1 ) ), f.getName( ) );
} else fieldMap.put( f.getName( ).substring( 0, 1 ).toUpperCase( ).concat( f.getName( ).substring( 1 ) ), f.getName( ) );
return fieldMap;
}
private static void addAccessControlList (final GroovyObject obj, final Map<String, String> paramFieldMap, Map bindingMap, String cannedACLString) {
AccessControlListType accessControlList;
ArrayList<Grant> grants;
if(bindingMap.containsKey("AccessControlPolicy")) {
AccessControlPolicyType accessControlPolicy = (AccessControlPolicyType) bindingMap.get("AccessControlPolicy");
accessControlList = accessControlPolicy.getAccessControlList();
grants = accessControlList.getGrants();
} else {
accessControlList = new AccessControlListType();
grants = new ArrayList<Grant>();
}
CanonicalUserType aws = new CanonicalUserType();
aws.setDisplayName("");
Grant grant = new Grant(new Grantee(aws), cannedACLString);
grants.add(grant);
accessControlList.setGrants(grants);
//set obj property
String acl = paramFieldMap.remove("AccessControlList");
if(acl != null) {
obj.setProperty(acl, accessControlList );
}
}
private String toUpperFirst(String string) {
return string.substring(0, 1).toUpperCase().concat(string.substring(1));
}
private boolean exactMatch(JSONObject jsonObject, Map formFields, List<String> policyItemNames) {
Iterator<String> iterator = jsonObject.keys();
boolean returnValue = false;
while(iterator.hasNext()) {
String key = iterator.next();
key = key.replaceAll("\\$", "");
policyItemNames.add(key);
try {
if(jsonObject.get(key).equals(formFields.get(key)))
returnValue = true;
else
returnValue = false;
} catch(Exception ex) {
ex.printStackTrace();
return false;
}
}
return returnValue;
}
private boolean partialMatch(JSONArray jsonArray, Map<String, String> formFields, List<String> policyItemNames) {
boolean returnValue = false;
if(jsonArray.size() != 3)
return false;
try {
String condition = (String) jsonArray.get(0);
String key = (String) jsonArray.get(1);
key = key.replaceAll("\\$", "");
policyItemNames.add(key);
String value = (String) jsonArray.get(2);
if(condition.contains("eq")) {
if(value.equals(formFields.get(key)))
returnValue = true;
} else if(condition.contains("starts-with")) {
if(!formFields.containsKey(key))
return false;
if(formFields.get(key).startsWith(value))
returnValue = true;
}
} catch(Exception ex) {
ex.printStackTrace();
return false;
}
return returnValue;
}
private String getMessageString(MappingHttpRequest httpRequest) {
ChannelBuffer buffer = httpRequest.getContent( );
buffer.markReaderIndex( );
byte[] read = new byte[buffer.readableBytes( )];
buffer.readBytes( read );
return new String( read );
}
private void insertChunk(WalrusDataMessage message) throws InterruptedException {
if(putQueue != null) {
boolean success = false;
int retry_count = 0;
do {
success = putQueue.offer(message, 500, TimeUnit.MILLISECONDS);
if(++retry_count > PUT_RETRY_COUNT) {
LOG.error("Tired of waiting for PUT. Giving up.");
putQueue = null;
}
} while((putQueue != null) && (!success));
}
}
private void handleHttpChunk(HttpChunk httpChunk) throws Exception {
ChannelBuffer buffer = httpChunk.getContent();
try {
buffer.markReaderIndex( );
byte[] read = new byte[buffer.readableBytes( )];
buffer.readBytes( read );
insertChunk(WalrusDataMessage.DataMessage(read));
if(httpChunk.isLast()) {
insertChunk(WalrusDataMessage.EOF());
}
} catch (Exception ex) {
LOG.error(ex, ex);
}
}
private void handleFirstChunk(MappingHttpRequest httpRequest, long dataLength) {
ChannelBuffer buffer = httpRequest.getContent();
try {
putQueue.put(WalrusDataMessage.StartOfData(dataLength));
buffer.markReaderIndex( );
byte[] read = new byte[buffer.readableBytes( )];
buffer.readBytes( read );
putQueue.put(WalrusDataMessage.DataMessage(read));
if(!httpRequest.isChunked())
putQueue.put(WalrusDataMessage.EOF());
} catch (Exception ex) {
LOG.error(ex, ex);
}
}
private void handleFirstChunk(MappingHttpRequest httpRequest, ChannelBuffer firstChunk, long dataLength) {
try {
putQueue.put(WalrusDataMessage.StartOfData(dataLength));
byte[] read = new byte[firstChunk.readableBytes( )];
firstChunk.readBytes( read );
putQueue.put(WalrusDataMessage.DataMessage(read));
if(!httpRequest.isChunked())
putQueue.put(WalrusDataMessage.EOF());
} catch (Exception ex) {
LOG.error(ex, ex);
}
}
public static synchronized WalrusDataMessenger getWriteMessenger() {
if (putMessenger == null) {
putMessenger = new WalrusDataMessenger();
}
return putMessenger;
}
}