001/* 002 * Copyright 2017 the original author or authors. 003 * 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package net.sf.jkniv.camel.sap.jco3; 020 021import java.util.HashMap; 022import java.util.Properties; 023 024import com.sap.conn.jco.ext.DataProviderException; 025import com.sap.conn.jco.ext.DestinationDataEventListener; 026import com.sap.conn.jco.ext.DestinationDataProvider; 027 028/** 029 * Each application using Java Connector 3 deals with destinations. A destination represents a logical address 030 * of an ABAP system and thus separates the destination configuration from application logic. JCo retrieves 031 * the destination parameters required at runtime from DestinationDataProvider and ServerDataProvider registered 032 * in the runtime environment. If no provider is registered, JCo uses the default implementation that reads the 033 * configuration from a properties file. It is expected that each environment provides a suitable 034 * implementation that meets security and other requirements. Furthermore, only one DestinationDataProvider 035 * and only one ServerDataProvider can be registered per process. The reason behind this design decision 036 * is the following: the provider implementations are part of the environment infrastructure. 037 * The implementation should not be application specific, and in particular must be separated from 038 * application logic. 039 */ 040public class SapJcoDestinationDataProvider implements DestinationDataProvider 041{ 042 private DestinationDataEventListener eL; 043 private HashMap<String, Properties> propsByDestName = new HashMap<String, Properties>(); 044 045 /** 046 * The name of SAP <code>JCoDestination</code> name that identifies a physical destination of a function call. 047 */ 048 public Properties getDestinationProperties(String destName) 049 { 050 try 051 { 052 //read the destination from DB 053 Properties p = propsByDestName.get(destName); 054 055 if (p != null) 056 { 057 //check if all is correct, for example 058 if (p.isEmpty()) 059 throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, 060 "destination [" + destName + "] configuration is incorrect", null); 061 062 return p; 063 } 064 return null; 065 } 066 catch (RuntimeException re) 067 { 068 throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, 069 "Internal error to get config from destination [" + destName + "]", re); 070 } 071 } 072 073 /** 074 * An implementation supporting events has to retain the eventListener instance provided 075 * by the JCo runtime. This listener instance shall be used to notify the JCo runtime 076 * about all changes in destination configurations. 077 * 078 * @param eventListener The DestinationDataEventListener interface reacts on the events 079 * that a DestinationDataProvider could fire if the destination configuration was changed 080 */ 081 public void setDestinationDataEventListener(DestinationDataEventListener eventListener) 082 { 083 this.eL = eventListener; 084 } 085 086 public boolean isRegistered() 087 { 088 return (this.eL != null); 089 } 090 091 public boolean hasDestName(String destName) 092 { 093 return propsByDestName.containsKey(destName); 094 } 095 096 public boolean supportsEvents() 097 { 098 return true; 099 } 100 101 /** 102 * Update the connect properties from a specific <code>destName</code> 103 * @param destName the name of <code>JCoDestination</code> 104 * @param properties connection properties 105 */ 106 public void changeProperties(String destName, Properties properties) 107 { 108 synchronized (propsByDestName) 109 { 110 if (properties == null) 111 { 112 if (propsByDestName.remove(destName) != null) 113 eL.deleted(destName); 114 } 115 else 116 { 117 propsByDestName.put(destName, properties); 118 eL.updated(destName); // create or updated 119 } 120 } 121 } 122 123}