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

co.realtime.storage.Rest Maven / Gradle / Ivy

The newest version!
package co.realtime.storage;

import ibt.ortc.api.OnRestWebserviceResponse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import co.realtime.storage.StorageRef.StorageOrder;
import co.realtime.storage.entities.TableMetadata;
import co.realtime.storage.ext.OnBooleanResponse;
import co.realtime.storage.ext.OnError;
import co.realtime.storage.ext.OnItemSnapshot;
import co.realtime.storage.ext.OnRole;
import co.realtime.storage.ext.OnRoleName;
import co.realtime.storage.ext.OnTableCreation;
import co.realtime.storage.ext.OnTableMetadata;
import co.realtime.storage.ext.OnTableSnapshot;
import co.realtime.storage.ext.OnTableUpdate;
import co.realtime.storage.ext.StorageException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

class Rest {
	enum RestType {
		AUTHENTICATE("authenticate"),
		ISAUTHENTICATED("isAuthenticated"),
		LISTROLES("listRoles"),
		GETROLES("getRoles"),
		GETROLE("getRole"),
		DELETEROLE("deleteRole"),
		SETROLE("setRole"),
		UPDATEROLE("updateRole"),
		LISTITEMS("listItems"), 
		QUERYITEMS("queryItems"), 
		GETITEM("getItem"), 
		PUTITEM("putItem"), 
		UPDATEITEM("updateItem"), 
		DELETEITEM("deleteItem"), 
		CREATETABLE("createTable"), 
		UPDATETABLE("updateTable"), 
		DELETETABLE("deleteTable"), 
		LISTTABLES("listTables"), 
		DESCRIBETABLE("describeTable"), 
		INCR("incr"), 
		DECR("decr");

		private final String restName;

		private RestType(String s) {
			restName = s;
		}

		public String toString() {
			return restName;
		}
	};

	StorageContext context;
	RestType type;
	TableRef table;
	URL requestUrl;
	PostBodyBuilder bodyBuilder;
	private LinkedHashMap lastStopKey;
	private String lastStopTable;
	private ArrayList> allItems;
	
	public OnError onError = null;
	public OnTableSnapshot onTableSnapshot = null;
	public OnBooleanResponse onBooleanResponse = null;
	public OnItemSnapshot onItemSnapshot = null;
	public OnTableMetadata onTableMetadata = null;
	public OnTableCreation onTableCreation = null;
	public OnTableUpdate onTableUpdate = null;
	public OnRole onRole = null;
	public OnRoleName onRoleName = null;
	OnRestCompleted onRestCompleted = null;
	public String rawBody = null;
	public StorageOrder order = StorageOrder.NULL;
	public Long limit = null;

	Rest(StorageContext context, RestType type, PostBodyBuilder bodyBuilder, TableRef table) {
		this.context = context;
		this.type = type;
		this.bodyBuilder = bodyBuilder;
		this.table = table;
		this.requestUrl = null;
		this.lastStopKey = null;
		this.lastStopTable = null;
		this.allItems = new ArrayList>();
		this.limit = (Long) bodyBuilder.getObject("limit");
	}

	void process() {
		try {
			resolveUrl();
		} catch (Exception e) {
			if (this.onError != null)
			this.onError.run(1002, e.getMessage());
			return;
		}
		if (this.requestUrl == null) {
			this.context.lastBalancerResponse = null;
			if (this.onError != null)
				this.onError.run(1003, "Can not get response from balancer!");
			return;
		}
		if (lastStopKey != null)
			bodyBuilder.addObject("startKey", lastStopKey);

		if(lastStopTable!=null){
			bodyBuilder.addObject("startTable", lastStopTable);
		}

		if (this.type == RestType.QUERYITEMS && this.order == StorageOrder.DESC){
			bodyBuilder.addObject("searchForward",false);
		}

		String rBody;
		try {
			rBody = (this.rawBody != null ? this.rawBody : this.bodyBuilder.getBody());
		} catch (JsonProcessingException e) {
			if (this.onError != null)
				this.onError.run(1004, e.getMessage());
			return;
		}

		RestWebservice.postAsync(this.requestUrl, rBody,
				new OnRestWebserviceResponse() {
					@SuppressWarnings("unchecked")
					@Override
					public void run(Exception e, String r) {
						if (onRestCompleted != null)
							onRestCompleted.run();
						if (e != null) {
							if (context.isCluster && context.lastBalancerResponse != null) {
								context.lastBalancerResponse = null;
								process();
							} else {
								if (onError != null)
									onError.run(1005, e.getMessage());
							}
						} else {
							ObjectMapper mapper = new ObjectMapper();

							Map data;
							try {
								data = mapper.readValue(r, Map.class);
							} catch (Exception ex) {
								if (onError != null)
									onError.run(1006, ex.getMessage());
								return;
							}
							LinkedHashMap error = (LinkedHashMap) data.get("error");
							if (error != null) {
								if (onError != null)
									onError.run((Integer) error.get("code"),(String) error.get("message"));
							} else {
								if (type == RestType.LISTITEMS || type == RestType.QUERYITEMS) {
									LinkedHashMap rdata = (LinkedHashMap) data.get("data");
									LinkedHashMap stopKey = (LinkedHashMap) rdata.get("stopKey");
									ArrayList> items = (ArrayList>) rdata.get("items");
									allItems.addAll(items);

									if ((type != RestType.QUERYITEMS || (limit != null && limit > allItems.size())) && stopKey != null) {
										lastStopKey = stopKey;
										process();
										return;
									}
								}

								if(type == RestType.LISTTABLES){
									LinkedHashMap rData = (LinkedHashMap)data.get("data");
									String stopTable = (String) rData.get("stopTable");
									ArrayList tables = (ArrayList) rData.get("tables");
									if(!stopTable.isEmpty() && tables.isEmpty()){
										lastStopTable = stopTable;
										process();
										return;
									}
								}

								switch (type) {
								case AUTHENTICATE:
									ProcessRestResponse.processAuthenticate(
											data, onBooleanResponse);
									break;
								case ISAUTHENTICATED:
									ProcessRestResponse.processIsAuthenticated(
											data, onBooleanResponse);
									break;		
								case LISTROLES:
									ProcessRestResponse.processListRoles(
											data, onRoleName);
									break;
								case GETROLES:
									ProcessRestResponse.processGetRoles(
											data, onRole);
									break;
								case GETROLE:
									ProcessRestResponse.processGetRole(
											data, onRole);
									break;
								case DELETEROLE:
									ProcessRestResponse.processDeleteRole(
											data, onBooleanResponse);
									break;
								case SETROLE:
									ProcessRestResponse.processSetRole(
											data, onBooleanResponse);
									break;
								case UPDATEROLE:
									ProcessRestResponse.processUpdateRole(
											data, onBooleanResponse);
									break;
								case LISTITEMS:
									String sortKey = null;
									if (order != StorageOrder.NULL) {
										TableMetadata tm = context.getTableMeta(table.name());
										sortKey = tm.getSecondaryKeyName();
										if (sortKey == null)
											sortKey = tm.getPrimaryKeyName();
									}
									ProcessRestResponse.processListItems(allItems, table, onItemSnapshot, order, sortKey, limit);
									break;
								case QUERYITEMS:
									ProcessRestResponse.processQueryItems(allItems, table, onItemSnapshot);
									break;
								case GETITEM:
									ProcessRestResponse.processGetItem(data, table, onItemSnapshot);
									break;
								case PUTITEM:
									ProcessRestResponse.processPutItem(data, table, onItemSnapshot);
									break;
								case UPDATEITEM:
									ProcessRestResponse.processUpdateItem(data, table, onItemSnapshot);
									break;
								case DELETEITEM:
									ProcessRestResponse.processDelItem(data, table, onItemSnapshot);
									break;
								case CREATETABLE:
									ProcessRestResponse.processCreateTable(data, onTableCreation);
									break;
								case UPDATETABLE:
									ProcessRestResponse.processUpdateTable(data, onTableUpdate);
									break;
								case DELETETABLE:
									ProcessRestResponse.processDeleteTable(data, onBooleanResponse);
									break;
								case LISTTABLES:
									ProcessRestResponse.processListTables(data, context, onTableSnapshot);
									break;
								case DESCRIBETABLE:
									ProcessRestResponse.processDescribeTable(data, context, onTableMetadata);
									break;
								case INCR:
								case DECR:
									ProcessRestResponse.processInDeCrResponse(data, table, onItemSnapshot);
									break;
								}
							}
						}
					}
				});
	}

	// will put the server url with rest path to this.requestUrl
	void resolveUrl() throws Exception {
		String tempUrl;
		if (context.isCluster) {
			if (this.context.lastBalancerResponse != null) {
				tempUrl = this.context.lastBalancerResponse;
			} 
                        else {
				String urlString = context.url + "?appkey=" + context.applicationKey;
				URL url = new URL(urlString);
				String balancerResponse = urlString.startsWith("https:") ? secureBalancerRequest(url) : unsecureBalancerRequest(url);
				if (balancerResponse == null) {
					throw new StorageException("Cannot get response from balancer!");
				}
				JSONObject obj = (JSONObject) JSONValue.parse(balancerResponse);
				tempUrl = (String) obj.get("url");
				this.context.lastBalancerResponse = tempUrl;
			}
		} else {
			tempUrl = context.url;
		}
		tempUrl += tempUrl.substring(tempUrl.length() - 1).equals("/") ? this.type.toString() : "/" + this.type.toString();
		this.requestUrl = new URL(tempUrl);
	}

	private String unsecureBalancerRequest(URL url) throws IOException {
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setRequestProperty("user-agent", "storage-java-client");
		BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		String result = "";
		String line;
		while ((line = rd.readLine()) != null) {
			result += line;
		}
		rd.close();
		return result;
	}

	private String secureBalancerRequest(URL url) throws Exception { // throws
													// UnknownHostException,
													// IOException {
		HttpsURLConnection connection = null;
		StringBuilder result = new StringBuilder(16);

		// connection.setDoOutput(true);

		try {
			connection = (HttpsURLConnection) url.openConnection();
			BufferedReader rd = null;

			try {
				if (connection.getResponseCode() != 200) {
					// CAUSE: Reliance on default encoding
					rd = new BufferedReader(new InputStreamReader(
							connection.getErrorStream(), "UTF-8"));
					String line = rd.readLine();
					while (line != null) {
						result.append(line);
						line = rd.readLine();
					}
					rd.close();
					throw new Exception(result.toString());
				} else {
					rd = new BufferedReader(new InputStreamReader(
							connection.getInputStream(), "UTF-8"));
					String line = rd.readLine();
					while (line != null) {
						result.append(line);
						line = rd.readLine();
					}

				}
				// CAUSE: Method may fail to close stream on exception
			} finally {
				if (rd != null) {
					rd.close();
				}
			}
			// CAUSE: Method may fail to close connection on exception
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}

		return result.toString();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy