/*
* � Copyright IBM Corp. 2015
*
* 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.
*/
/*
* Author: Tony McGuckin (tony.mcguckin@ie.ibm.com)
* Date: 09 Apr 2015 (or earlier)
* BluemixContext.java
*/
package com.ibm.xsp.bluemix.util.context;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.Vector;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import lotus.domino.NotesException;
import lotus.domino.Session;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.util.io.json.JsonException;
import com.ibm.commons.util.io.json.JsonJavaArray;
import com.ibm.commons.util.io.json.JsonJavaFactory;
import com.ibm.commons.util.io.json.JsonJavaObject;
import com.ibm.commons.util.io.json.JsonParser;
import com.ibm.xsp.context.FacesContextEx;
import com.ibm.xsp.extlib.util.ExtLibUtil;
/**
* IBM Bluemix/XPages Context class
*
* @author tony.mcguckin@ie.ibm.com
*/
public class BluemixContext{
// VCAP env vars
private String _VCAP_SERVICES;
private boolean _VCAP_SERVICES_set = false;
private JsonJavaObject _VCAP_SERVICES_asJson;
private boolean _VCAP_SERVICES_asJson_set;
private String _VCAP_APP_PORT;
private String _VCAP_APP_HOST;
private String _VCAP_APPLICATION;
private String _PORT;
private String _MEMORY_LIMIT;
private String _USER;
private String _HOME;
private String _PWD;
private String _TMPDIR;
// XSP env vars
private String _APP_HOME_URL;
private String _APP_PRELOAD_DB;
private String _APP_VERBOSE_STAGING;
private String _APP_INCLUDE_XPAGES_TOOLBOX;
private String _APP_JVM_HEAPSIZE;
// XSP env vars ctd. - Added in R15 of Extlib
private String _APP_REMOTE_DATA_SERVER_NAME;
private String _APP_REMOTE_DATA_SERVER_ADDRESS;
private String _APP_RUNTIME_SERVER_NAME;
private String _APP_RUNTIME_SERVER_IDFILE;
private String _APP_DA_ENABLED;
private String _APP_DA_DOMAIN;
private String _APP_DA_ADDRESS_BOOK;
private Boolean _onBluemix;
private static String XPAGES_DATA_SERVICE_NAME = "XPagesData"; // $NON-NLS-1$
// ------------------------------------------------
// ------------------------------------------------
public DataService getDataServiceByName(final String instanceName) {
return getDataService(/*isByName*/true, instanceName);
}
public DataService getDataService() {
return getDataService(/*isByName*/false, /*instanceName*/null);
}
private DataService getDataService(boolean isByName, final String instanceName) {
checkOnBluemix();
JsonJavaObject asJson = getVCAP_SERVICES_asJson();
if( null == asJson ){
throw new FacesException("No services found."); // $NLX-BluemixContext.Noservicesfound-1$
}
if( !asJson.containsKey(XPAGES_DATA_SERVICE_NAME) ){
throw new FacesException("No data services found."); // $NLX-BluemixContext.Nodataservicesfound-1$
}
JsonJavaArray services = asJson.getAsArray(XPAGES_DATA_SERVICE_NAME);
if( null == services ){
throw new FacesException("Bad syntax: not array."); // $NLX-BluemixContext.Badsyntaxnotarray-1$
}
if( 0 == services.length() ){
throw new FacesException("Data services count is zero."); // $NLX-BluemixContext.Dataservicescountiszero-1$
}
for (Iterator<Object> iterator = services.iterator(); iterator.hasNext();) {
Object object = iterator.next();
if (object instanceof JsonJavaObject) {
JsonJavaObject service = (JsonJavaObject) object;
if( ! isByName ){
return new DataService(service);
}else{ // isByName
String name = service.getAsString("name"); // $NON-NLS-1$
if (null != name && name.equals(instanceName)) {
return new DataService(service);
}
}
}else{
String userMsg = msgDataServiceArrayBadType(object);
throw new FacesException(userMsg);
}
}
if( !isByName ){
throw new FacesException("No data service found."); // $NLX-BluemixContext.Nodataservicefound-1$
}else{ // isByName
String userMsg = "No data service with name {0}"; // $NLX-BluemixContext.Nodataservicewithname0-1$
userMsg = StringUtil.format(userMsg, instanceName);
throw new FacesException(userMsg);
}
}
/**
* @param object
* @return
*/
private String msgDataServiceArrayBadType(Object object) {
String type = (null == object)? null : object.getClass().getName();
String userMsg = "Bad object type in data services array: {0}"; // $NLX-BluemixContext.Badobjecttypeindataservicesarray0-1$
userMsg = StringUtil.format(userMsg, type);
return userMsg;
}
public boolean isDataServiceExists() {
checkOnBluemix();
JsonJavaObject asJson = getVCAP_SERVICES_asJson();
if( null == asJson ){
return false;
}
if( !asJson.containsKey(XPAGES_DATA_SERVICE_NAME) ){
return false;
}
JsonJavaArray services = asJson.getAsArray(XPAGES_DATA_SERVICE_NAME);
if( null == services ){
return false;
}
if( 0 == services.length() ){
return false;
}
for (Iterator<Object> iterator = services.iterator(); iterator.hasNext();) {
Object object = iterator.next();
if (object instanceof JsonJavaObject) {
return true;
}
}
return false;
}
public boolean isDataServiceByNameExists(final String instanceName) {
checkOnBluemix();
JsonJavaObject asJson = getVCAP_SERVICES_asJson();
if( null == asJson ){
return false;
}
if( ! asJson.containsKey(XPAGES_DATA_SERVICE_NAME) ){
return false;
}
JsonJavaArray services = asJson.getAsArray(XPAGES_DATA_SERVICE_NAME);
if( null == services ){
return false;
}
if( 0 == services.length() ){
return false;
}
for (Iterator<Object> iterator = services.iterator(); iterator.hasNext();) {
Object object = iterator.next();
if (object instanceof JsonJavaObject) {
JsonJavaObject service = (JsonJavaObject) object;
String name = service.getAsString("name"); // $NON-NLS-1$
if (null != name && name.equals(instanceName)) {
return true;
} // else continue looping
}else{
String userMsg = msgDataServiceArrayBadType(object);
throw new FacesException(userMsg);
}
}
return false;
}
// ------------------------------------------------
public boolean isHybridApplication() {
checkOnBluemix();
try{
Session session = ExtLibUtil.getCurrentSession();
String serverName = session.getServerName();
String defaultServerNameFull = "CN=vcap/O=Bluemix"; // $NON-NLS-1$
String defaultServerNameShort = "vcap/Bluemix"; // $NON-NLS-1$
if(serverName != null && !serverName.equals(defaultServerNameFull) && !serverName.equals(defaultServerNameShort)) {
return true;
}
}catch(NotesException ne) {
throw new FacesException(ne.getMessage());
}
return false;
}
public String findHybridDatabaseName(String dbPath) {
String remoteName = getAPP_REMOTE_DATA_SERVER_NAME();
if(remoteName != null) {
String hybridDb = concatRemoveSeparators(remoteName, dbPath, '/');
return hybridDb;
}
return null;
}
/**
* Concatenate server name with dbPath, ensuring that the result doesn't start
* with a '/', doesn't end with a '/', and doesn't have a '/' in the middle.
* @ibm-api
*/
private String concatRemoveSeparators(String serverName, String path, char sep) {
StringBuilder b = new StringBuilder();
if(StringUtil.isNotEmpty(serverName)) {
int startServer = 0;
int endServer = serverName.length();
if(serverName.charAt(0)==sep) {
startServer = 1;
}
if(serverName.charAt(endServer-1)==sep) {
endServer = serverName.length()-1;
}
if(endServer > startServer) {
b.append(serverName,startServer,endServer);
// Add bang bang after server name
b.append("!!");
}
}
if(StringUtil.isNotEmpty(path)) {
int startPath = 0;
int endPath = path.length();
if(path.charAt(0)==sep) {
startPath = 1;
}
if(path.charAt(endPath-1)==sep) {
endPath = path.length()-1;
}
if(endPath > startPath) {
b.append(path,startPath,endPath);
}
}
return b.toString();
}
public Vector<String> atHybridDbName(String dbPath){
String remoteAddr = getAPP_REMOTE_DATA_SERVER_ADDRESS();
if(remoteAddr != null) {
Vector<String> v = new Vector<String>();
v.add(remoteAddr);
v.add(dbPath);
return v;
}
return null;
}
// ------------------------------------------------
// public JsonJavaObject getServiceInstance(final String serviceName, final String instanceName) {
// if (null != _VCAP_SERVICES && _VCAP_SERVICES.containsKey(serviceName)) {
// JsonJavaArray services = _VCAP_SERVICES.getAsArray(serviceName);
// if (null != services && services.length() > 0) {
// for (Iterator<Object> iterator = services.iterator(); iterator.hasNext();) {
// Object object = (Object) iterator.next();
// if (object instanceof JsonJavaObject) {
// JsonJavaObject service = (JsonJavaObject) object;
// if (null != service) {
// String name = service.getAsString("name"); // $NON-NLS-1$
// if (null != name && name.equalsIgnoreCase(instanceName)) {
// return service;
// }
// }
// }
// }
// }
// }
// return null;
// }
// ------------------------------------------------
/*package-private*/ BluemixContext() {
}
// ------------------------------------------------
// buildpack java.policy includes a set of extended set of
// runtime permissions for the following env vars...
// ie: permission java.lang.RuntimePermission "getenv.APP_HOME_URL";
// for any env var not listed, a security permission will be thrown
// when someone tries to read such a property...
public String getVCAP_SERVICES() {
checkOnBluemix();
if( _VCAP_SERVICES_set ){
return _VCAP_SERVICES;
}
// Note, in an on-premise environment, by default this call to read an environment variable
// will throw a security exception.
// However in Bluemix, the java.policy file allows support for reading a pre-defined
// list of environment variables, so this does not throw an exception.
_VCAP_SERVICES = java.lang.System.getenv("VCAP_SERVICES"); // $NON-NLS-1$
_VCAP_SERVICES_set = true;
return _VCAP_SERVICES;
}
private JsonJavaObject getVCAP_SERVICES_asJson() {
checkOnBluemix();
if( _VCAP_SERVICES_asJson_set ){
return _VCAP_SERVICES_asJson;
}
JsonJavaObject jsonObj;
final String asString = getVCAP_SERVICES();
if( null == asString || asString.isEmpty() ){
jsonObj = null;
}else{
Object jsonAnyType;
jsonAnyType = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
// privileged code goes here:
try {
Object result = JsonParser.fromJson(JsonJavaFactory.instanceEx, asString);
return result;
} catch (JsonException e) {
throw new FacesException("Problem parsing JSON in VCAP_SERVICES environment variable", e); // $NLX-BluemixContext.ProblemparsingJSONinVCAP_SERVICES-1$
}
}
});
if( !(jsonAnyType instanceof JsonJavaObject) ){
String jsonValue = (null == jsonAnyType)? null : jsonAnyType.toString();
String userMsg = "Unexpected type in VCAP_SERVICES environment variable. Not JSON Object. Is: {0}"; // $NLX-BluemixContext.UnexpectedtypeinVCAP_SERVICESenvi-1$
userMsg = StringUtil.format(userMsg, jsonValue);
throw new FacesException(userMsg);
}
/*
* if (null != _VCAP_SERVICES) { for (Iterator<String> i =
* _VCAP_SERVICES.getJsonProperties(); i.hasNext();) {
* String jso_property = (String) i.next();
* System.out.println("jso_property: " + jso_property); } }
*/
// try {
jsonObj = (JsonJavaObject) jsonAnyType;
// } catch (Exception e) {
// e.printStackTrace();
// }
}
_VCAP_SERVICES_asJson = jsonObj;
_VCAP_SERVICES_asJson_set = true;
return _VCAP_SERVICES_asJson;
}
// ------------------------------------------------
public String getVCAP_APP_PORT() {
checkOnBluemix();
if (null == _VCAP_APP_PORT) {
_VCAP_APP_PORT = java.lang.System.getenv("VCAP_APP_PORT"); // $NON-NLS-1$
}
return _VCAP_APP_PORT;
}
// ------------------------------------------------
public String getVCAP_APP_HOST() {
checkOnBluemix();
if (null == _VCAP_APP_HOST) {
_VCAP_APP_HOST = java.lang.System.getenv("VCAP_APP_HOST"); // $NON-NLS-1$
}
return _VCAP_APP_HOST;
}
// ------------------------------------------------
public String getVCAP_APPLICATION() {
checkOnBluemix();
if (null == _VCAP_APPLICATION) {
_VCAP_APPLICATION = java.lang.System.getenv("VCAP_APPLICATION"); // $NON-NLS-1$
}
return _VCAP_APPLICATION;
}
// ------------------------------------------------
public String getPORT() {
checkOnBluemix();
if (null == _PORT) {
_PORT = java.lang.System.getenv("PORT"); // $NON-NLS-1$
}
return _PORT;
}
// ------------------------------------------------
public String getMEMORY_LIMIT() {
checkOnBluemix();
if (null == _MEMORY_LIMIT) {
_MEMORY_LIMIT = java.lang.System.getenv("MEMORY_LIMIT"); // $NON-NLS-1$
}
return _MEMORY_LIMIT;
}
// ------------------------------------------------
public String getUSER() {
checkOnBluemix();
if (null == _USER) {
_USER = java.lang.System.getenv("USER"); // $NON-NLS-1$
}
return _USER;
}
// ------------------------------------------------
public String getHOME() {
checkOnBluemix();
if (null == _HOME) {
_HOME = java.lang.System.getenv("HOME"); // $NON-NLS-1$
}
return _HOME;
}
// ------------------------------------------------
public String getPWD() {
checkOnBluemix();
if (null == _PWD) {
_PWD = java.lang.System.getenv("PWD"); // $NON-NLS-1$
}
return _PWD;
}
// ------------------------------------------------
public String getTMPDIR() {
checkOnBluemix();
if (null == _TMPDIR) {
_TMPDIR = java.lang.System.getenv("TMPDIR"); // $NON-NLS-1$
}
return _TMPDIR;
}
// ------------------------------------------------
public String getAPP_HOME_URL() {
checkOnBluemix();
if (null == _APP_HOME_URL) {
_APP_HOME_URL = java.lang.System.getenv("APP_HOME_URL"); // $NON-NLS-1$
}
return _APP_HOME_URL;
}
// ------------------------------------------------
public String getAPP_PRELOAD_DB() {
checkOnBluemix();
if (null == _APP_PRELOAD_DB) {
_APP_PRELOAD_DB = java.lang.System.getenv("APP_PRELOAD_DB"); // $NON-NLS-1$
}
return _APP_PRELOAD_DB;
}
// ------------------------------------------------
public String getAPP_VERBOSE_STAGING() {
checkOnBluemix();
if (null == _APP_VERBOSE_STAGING) {
_APP_VERBOSE_STAGING = java.lang.System.getenv("APP_VERBOSE_STAGING"); // $NON-NLS-1$
}
return _APP_VERBOSE_STAGING;
}
// ------------------------------------------------
public String getAPP_INCLUDE_XPAGES_TOOLBOX() {
checkOnBluemix();
if (null == _APP_INCLUDE_XPAGES_TOOLBOX) {
_APP_INCLUDE_XPAGES_TOOLBOX = java.lang.System.getenv("APP_INCLUDE_XPAGES_TOOLBOX"); // $NON-NLS-1$
}
return _APP_INCLUDE_XPAGES_TOOLBOX;
}
// ------------------------------------------------
public String getAPP_JVM_HEAPSIZE() {
checkOnBluemix();
if (null == _APP_JVM_HEAPSIZE) {
_APP_JVM_HEAPSIZE = java.lang.System.getenv("APP_JVM_HEAPSIZE"); // $NON-NLS-1$
}
return _APP_JVM_HEAPSIZE;
}
// ------------------------------------------------
public String getAPP_REMOTE_DATA_SERVER_NAME() {
checkOnBluemix();
if (null == _APP_REMOTE_DATA_SERVER_NAME) {
_APP_REMOTE_DATA_SERVER_NAME = java.lang.System.getenv("APP_REMOTE_DATA_SERVER_NAME"); // $NON-NLS-1$
}
return _APP_REMOTE_DATA_SERVER_NAME;
}
// ------------------------------------------------
public String getAPP_REMOTE_DATA_SERVER_ADDRESS() {
checkOnBluemix();
if (null == _APP_REMOTE_DATA_SERVER_ADDRESS) {
_APP_REMOTE_DATA_SERVER_ADDRESS = java.lang.System.getenv("APP_REMOTE_DATA_SERVER_ADDRESS"); // $NON-NLS-1$
}
return _APP_REMOTE_DATA_SERVER_ADDRESS;
}
// ------------------------------------------------
public String getAPP_RUNTIME_SERVER_NAME() {
checkOnBluemix();
if (null == _APP_RUNTIME_SERVER_NAME) {
_APP_RUNTIME_SERVER_NAME = java.lang.System.getenv("APP_RUNTIME_SERVER_NAME"); // $NON-NLS-1$
}
return _APP_RUNTIME_SERVER_NAME;
}
// ------------------------------------------------
public String getAPP_RUNTIME_SERVER_IDFILE() {
checkOnBluemix();
if (null == _APP_RUNTIME_SERVER_IDFILE) {
_APP_RUNTIME_SERVER_IDFILE = java.lang.System.getenv("APP_RUNTIME_SERVER_IDFILE"); // $NON-NLS-1$
}
return _APP_RUNTIME_SERVER_IDFILE;
}
// ------------------------------------------------
public String getAPP_DA_ENABLED() {
checkOnBluemix();
if (null == _APP_DA_ENABLED) {
_APP_DA_ENABLED = java.lang.System.getenv("APP_DA_ENABLED"); // $NON-NLS-1$
}
return _APP_DA_ENABLED;
}
// ------------------------------------------------
public String getAPP_DA_DOMAIN() {
checkOnBluemix();
if (null == _APP_DA_DOMAIN) {
_APP_DA_DOMAIN = java.lang.System.getenv("APP_DA_DOMAIN"); // $NON-NLS-1$
}
return _APP_DA_DOMAIN;
}
// ------------------------------------------------
public String getAPP_DA_ADDRESS_BOOK() {
checkOnBluemix();
if (null == _APP_DA_ADDRESS_BOOK) {
_APP_DA_ADDRESS_BOOK = java.lang.System.getenv("APP_DA_ADDRESS_BOOK"); // $NON-NLS-1$
}
return _APP_DA_ADDRESS_BOOK;
}
// ------------------------------------------------
public boolean isRunningOnBluemix() {
if( null != _onBluemix ){
return _onBluemix.booleanValue();
}
// when on bluemix, xsp.bluemix.platform=1 will exist
// inside the global xsp.properties file...
boolean detectedOnBluemix;
String isBluemixPlatform = ((FacesContextEx) FacesContext.getCurrentInstance()).getProperty("xsp.bluemix.platform"); // $NON-NLS-1$
if (StringUtil.isEmpty(isBluemixPlatform) || StringUtil.equals(isBluemixPlatform, "0")) { // $NON-NLS-1$
detectedOnBluemix = false;
}else{
detectedOnBluemix = (null != java.lang.System.getenv("VCAP_APP_PORT")); // $NON-NLS-1$
}
_onBluemix = Boolean.valueOf(detectedOnBluemix);
return detectedOnBluemix;
}
private void checkOnBluemix(){
if( !isRunningOnBluemix() ){
String productName = "IBM Bluemix"; //$NON-NLS-1$
String userMsg = "Not running in the {0} cloud platform."; // $NLX-BluemixContext.Notrunninginthe0cloudplatform-1$[[{0} is the product name "IBM Bluemix"]]
userMsg = StringUtil.format(userMsg, productName);
throw new FacesException(userMsg);
}
}
// ------------------------------------------------
public String getBuildPackVersion() {
checkOnBluemix();
// when on bluemix, xsp.buildpack.version=<version> will exist
// inside the global xsp.properties file...
String buildpackVersion = ((FacesContextEx) FacesContext.getCurrentInstance()).getProperty("xsp.buildpack.version"); // $NON-NLS-1$
if (StringUtil.isEmpty(buildpackVersion)) {
return null;
}
return buildpackVersion;
}
// ------------------------------------------------
} // end BluemixContext class