blob: ae72e22d9d8adb66053bc100534798d0937f5a32 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.rt.server.services.common.jdbc;
import java.lang.reflect.Method;
import java.security.Permission;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.scout.commons.BundleContextUtility;
import org.eclipse.scout.commons.NumberUtility;
import org.eclipse.scout.commons.annotations.ConfigOperation;
import org.eclipse.scout.commons.annotations.ConfigProperty;
import org.eclipse.scout.commons.annotations.Order;
import org.eclipse.scout.commons.exception.ProcessingException;
import org.eclipse.scout.commons.holders.IHolder;
import org.eclipse.scout.commons.holders.LongHolder;
import org.eclipse.scout.commons.holders.StringHolder;
import org.eclipse.scout.commons.logger.IScoutLogger;
import org.eclipse.scout.commons.logger.ScoutLogManager;
import org.eclipse.scout.commons.osgi.BundleClassDescriptor;
import org.eclipse.scout.rt.server.ThreadContext;
import org.eclipse.scout.rt.server.services.common.jdbc.internal.exec.PreparedStatementCache;
import org.eclipse.scout.rt.server.services.common.jdbc.internal.exec.StatementProcessor;
import org.eclipse.scout.rt.server.services.common.jdbc.internal.legacy.LegacyStatementBuilder;
import org.eclipse.scout.rt.server.services.common.jdbc.internal.pool.SqlConnectionBuilder;
import org.eclipse.scout.rt.server.services.common.jdbc.internal.pool.SqlConnectionPool;
import org.eclipse.scout.rt.server.services.common.jdbc.style.ISqlStyle;
import org.eclipse.scout.rt.server.services.common.jdbc.style.ISqlStyle2;
import org.eclipse.scout.rt.server.services.common.jdbc.style.OracleSqlStyle;
import org.eclipse.scout.rt.server.transaction.ITransaction;
import org.eclipse.scout.rt.server.transaction.ITransactionMember;
import org.eclipse.scout.rt.shared.ScoutTexts;
import org.eclipse.scout.rt.shared.services.common.code.ICodeService;
import org.eclipse.scout.rt.shared.services.common.jdbc.ILegacySqlQueryService;
import org.eclipse.scout.rt.shared.services.common.jdbc.LegacySearchFilter;
import org.eclipse.scout.rt.shared.services.common.jdbc.LegacySearchFilter.WhereToken;
import org.eclipse.scout.rt.shared.services.common.security.IAccessControlService;
import org.eclipse.scout.rt.shared.services.common.security.IPermissionService;
import org.eclipse.scout.service.AbstractService;
import org.eclipse.scout.service.IServiceInventory;
import org.eclipse.scout.service.SERVICES;
import org.osgi.framework.ServiceRegistration;
public abstract class AbstractSqlService extends AbstractService implements ISqlService, ILegacySqlQueryService, IAdaptable {
private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractSqlService.class);
public static final int DEFAULT_MEMORY_PREFETCH_SIZE = 1048576; // = 1MB default
private SqlConnectionPool m_pool;
private Class<? extends ScoutTexts> m_nlsProvider;
private ISqlStyle m_sqlStyle;
private String m_transactionMemberId;
private boolean m_directJdbcConnection;
private String m_jndiName;
private String m_jndiInitialContextFactory;
private String m_jndiProviderUrl;
private String m_jndiUrlPkgPrefixes;
private String m_jdbcMappingName;
private String m_jdbcDriverName;
private String m_jdbcProps;
private int m_jdbcPoolSize;
private long m_jdbcPoolConnectionLifetime;
private long m_jdbcPoolConnectionBusyTimeout;
private String m_defaultUser;
private String m_defaultPass;
private int m_queryCacheSize;
private int m_maxFetchMemorySize = DEFAULT_MEMORY_PREFETCH_SIZE;
//
private HashMap<String, List<BundleClassDescriptor>> m_permissionNameToDescriptor;
private HashMap<String, List<BundleClassDescriptor>> m_codeNameToDescriptor;
public AbstractSqlService() {
initConfig();
}
@SuppressWarnings("deprecation")
@Override
public void initializeService(ServiceRegistration registration) {
super.initializeService(registration);
// load code and permission names
m_permissionNameToDescriptor = new HashMap<String, List<BundleClassDescriptor>>();
IPermissionService psvc = SERVICES.getService(IPermissionService.class);
if (psvc != null) {
for (BundleClassDescriptor d : psvc.getAllPermissionClasses()) {
List<BundleClassDescriptor> list = m_permissionNameToDescriptor.get(d.getSimpleClassName());
if (list == null) {
list = new ArrayList<BundleClassDescriptor>();
m_permissionNameToDescriptor.put(d.getSimpleClassName(), list);
}
list.add(d);
//
list = m_permissionNameToDescriptor.get(d.getClassName());
if (list == null) {
list = new ArrayList<BundleClassDescriptor>();
m_permissionNameToDescriptor.put(d.getClassName(), list);
}
list.add(d);
}
}
m_codeNameToDescriptor = new HashMap<String, List<BundleClassDescriptor>>();
ICodeService csvc = SERVICES.getService(ICodeService.class);
if (csvc != null) {
for (BundleClassDescriptor d : csvc.getAllCodeTypeClasses("")) {
List<BundleClassDescriptor> list = m_codeNameToDescriptor.get(d.getSimpleClassName());
if (list == null) {
list = new ArrayList<BundleClassDescriptor>();
m_codeNameToDescriptor.put(d.getSimpleClassName(), list);
}
list.add(d);
//
list = m_codeNameToDescriptor.get(d.getClassName());
if (list == null) {
list = new ArrayList<BundleClassDescriptor>();
m_codeNameToDescriptor.put(d.getClassName(), list);
}
list.add(d);
}
}
}
/*
* Configuration
*/
@ConfigProperty(ConfigProperty.BOOLEAN)
@Order(10)
protected boolean getConfiguredDirectJdbcConnection() {
return true;
}
@ConfigProperty(ConfigProperty.STRING)
@Order(20)
protected String getConfiguredUsername() {
return null;
}
@ConfigProperty(ConfigProperty.STRING)
@Order(30)
protected String getConfiguredPassword() {
return null;
}
@ConfigProperty(ConfigProperty.NLS_PROVIDER)
@Order(70)
protected Class<? extends ScoutTexts> getConfiguredNlsProvider() {
return null;
}
@ConfigProperty(ConfigProperty.SQL_STYLE)
@Order(80)
protected Class<? extends ISqlStyle> getConfiguredSqlStyle() {
return null;
}
/**
* @deprecated use {@link #getConfiguredTransactionMemberId()} Will be removed in Release 3.10.
*/
@Deprecated
protected String getConfiguredXAResourceId() {
return getConfiguredTransactionMemberId();
}
@ConfigProperty(ConfigProperty.STRING)
@Order(90)
protected String getConfiguredTransactionMemberId() {
return null;
}
@ConfigProperty(ConfigProperty.STRING)
@Order(100)
protected String getConfiguredJdbcDriverName() {
return "oracle.jdbc.OracleDriver";
}
@ConfigProperty(ConfigProperty.STRING)
@Order(110)
protected String getConfiguredJdbcMappingName() {
return "jdbc:oracle:thin:@localhost:1521:ORCL";
}
@ConfigProperty(ConfigProperty.STRING)
@Order(120)
protected String getConfiguredJdbcProperties() {
return null;
}
@ConfigProperty(ConfigProperty.INTEGER)
@Order(130)
protected int getConfiguredJdbcPoolSize() {
return 25;
}
@ConfigProperty(ConfigProperty.LONG)
@Order(140)
protected long getConfiguredJdbcPoolConnectionLifetime() {
return 300000L;
}
@ConfigProperty(ConfigProperty.LONG)
@Order(150)
protected long getConfiguredJdbcPoolConnectionBusyTimeout() {
return 21600000L;
}
@ConfigProperty(ConfigProperty.INTEGER)
@Order(160)
protected int getConfiguredJdbcStatementCacheSize() {
return 25;
}
@ConfigProperty(ConfigProperty.STRING)
@Order(170)
protected String getConfiguredJndiName() {
return null;
}
@ConfigProperty(ConfigProperty.STRING)
@Order(180)
protected String getConfiguredJndiInitialContextFactory() {
return null;
}
@ConfigProperty(ConfigProperty.STRING)
@Order(190)
protected String getConfiguredJndiProviderUrl() {
return null;
}
@ConfigProperty(ConfigProperty.STRING)
@Order(200)
protected String getConfiguredJndiUrlPkgPrefixes() {
return null;
}
@ConfigOperation
@Order(10)
protected void execTestConnection(Connection conn) throws Throwable {
ISqlStyle s = getSqlStyle();
if (s != null) {
s.testConnection(conn);
}
}
@ConfigOperation
@Order(15)
protected void execAfterConnectionCreated(Connection conn) throws ProcessingException {
}
/**
* called just after the transaction has started
*/
@ConfigOperation
@Order(20)
protected void execBeginTransaction() throws ProcessingException {
}
@ConfigOperation
@Order(30)
protected Connection execCreateConnection() throws Throwable {
return leaseConnectionInternal();
}
@ConfigOperation
@Order(35)
protected void execReleaseConnection(Connection conn) throws Throwable {
releaseConnectionInternal(conn);
}
/**
* Custom functions that can be used in sql statements as binds or sql style independent functions
* <p>
* Default functions are<br>
* ::level(permissionClass) --> int //to resolve a permissin level by executing a permission<br>
* ::level(permissionLevel) --> int //to resolve a permissin level by its id<br>
* ::code(codeClass or codeTypeClass) --> the ID of the code or code type<br>
* ::text(textId) --> the text in the user sessions language
* <p>
* Examples:<br>
* ::level(UpdatePersonPermission)<br>
* ::level(UpdatePersonPermission.LEVEL_OWN)<br>
* <br>
* ::code(CompanyAddressCodeType.MainAddressCode)<br>
* ::code(MainAddressCode)<br>
* <br>
* ::text(SalutationMr)
* <p>
*
* @return a plain object value or in case of a null value preferrably a {@link IHolder} of the correct value type
*/
@ConfigOperation
@Order(40)
protected Object execCustomBindFunction(String functionName, String[] args, Object[] bindBases) throws ProcessingException {
if (functionName.equals("level")) {
if (args.length != 1) {
throw new IllegalArgumentException("expected 1 argument for function '" + functionName + "'");
}
String permissionClassName = args[0];
String levelField = null;
// eventually a level id?
int levelDot = permissionClassName.indexOf(".LEVEL_");
if (levelDot >= 0) {
levelField = permissionClassName.substring(levelDot + 1);
permissionClassName = permissionClassName.substring(0, levelDot);
}
Class permissionClass = loadBundleClassLenient(m_permissionNameToDescriptor, permissionClassName);
IAccessControlService accessControlService = SERVICES.getService(IAccessControlService.class);
Object ret = tryGetPermissionLevel(permissionClass, levelField, accessControlService);
return ret != null ? ret : new LongHolder();
}
else if (functionName.equals("code")) {
if (args.length != 1) {
throw new IllegalArgumentException("expected 1 argument for function '" + functionName + "'");
}
String codeClassName = args[0];
Class codeClass = loadBundleClassLenient(m_codeNameToDescriptor, codeClassName);
if (codeClass == null) {
throw new ProcessingException("cannot find class for code '" + args[0] + "'");
}
try {
Object ret = codeClass.getField("ID").get(null);
return ret != null ? ret : new LongHolder();
}
catch (Throwable t) {
throw new ProcessingException("ID of code '" + args[0] + "'", t);
}
}
else if (functionName.equals("text")) {
if (args.length < 1) {
throw new IllegalArgumentException("expected at least 1 argument for function '" + functionName + "'");
}
if (args.length == 1) {
String[] tmp = new String[2];
tmp[0] = args[0];
tmp[1] = null;
args = tmp;
}
try {
Method m = getNlsProvider().getMethod("get", new Class[]{String.class, String[].class});
Object ret = m.invoke(null, (Object[]) args);
return ret != null ? ret : new StringHolder();
}
catch (Throwable t) {
throw new ProcessingException("unknown function in DynamicNls, check 'getConfiguredNlsProvider' / 'getNlsProvider': get", t);
}
}
else {
throw new IllegalArgumentException("undefined function '" + functionName + "'");
}
}
private Object tryGetPermissionLevel(Class permissionClass, String levelField, IAccessControlService accessControlService) throws ProcessingException {
if (permissionClass == null) {
return null;
}
try {
if (levelField != null) {
return permissionClass.getField(levelField).get(null);
}
else {
Permission p = (Permission) permissionClass.newInstance();
return accessControlService.getPermissionLevel(p);
}
}
catch (Exception e) {
throw new ProcessingException("getLevel of permission '" + permissionClass + "'", e);
}
}
/**
* Called just before the transaction is being committed or rollbacked.<br>
* Do not call commit here, the flag is just meant as a hint.
* Statements are executed, even if the transaction is canceled.
*/
@ConfigOperation
@Order(50)
protected void execEndTransaction(boolean willBeCommitted) throws ProcessingException {
}
protected void initConfig() {
String tid = getConfiguredTransactionMemberId();
if (tid == null) {
tid = getClass().getSimpleName() + "." + "transaction";
}
setTransactionMemberId(tid);
setDirectJdbcConnection(getConfiguredDirectJdbcConnection());
setUsername(getConfiguredUsername());
setPassword(getConfiguredPassword());
setJndiName(getConfiguredJndiName());
setJndiInitialContextFactory(getConfiguredJndiInitialContextFactory());
setJndiProviderUrl(getConfiguredJndiProviderUrl());
setJndiUrlPkgPrefixes(getConfiguredJndiUrlPkgPrefixes());
setJdbcMappingName(getConfiguredJdbcMappingName());
setJdbcDriverName(getConfiguredJdbcDriverName());
setJdbcProperties(getConfiguredJdbcProperties());
setJdbcStatementCacheSize(getConfiguredJdbcStatementCacheSize());
setJdbcPoolSize(getConfiguredJdbcPoolSize());
setJdbcPoolConnectionBusyTimeout(getConfiguredJdbcPoolConnectionBusyTimeout());
setJdbcPoolConnectionLifetime(getConfiguredJdbcPoolConnectionLifetime());
setNlsProvider(getConfiguredNlsProvider());
// sql style
Class<? extends ISqlStyle> styleClass = getConfiguredSqlStyle();
if (styleClass != null) {
try {
setSqlStyle(styleClass.newInstance());
}
catch (Exception e) {
LOG.warn(null, e);
}
}
else {
setSqlStyle(new OracleSqlStyle());
}
}
/*
* Runtime
*/
public void callbackAfterConnectionCreated(Connection conn) throws ProcessingException {
execAfterConnectionCreated(conn);
}
public void callbackTestConnection(Connection conn) throws Throwable {
execTestConnection(conn);
}
public Object callbackCustomBindFunction(String functionName, String[] args, Object[] bindBases) throws ProcessingException {
return execCustomBindFunction(functionName, args, bindBases);
}
@Override
public String getTransactionMemberId() {
return m_transactionMemberId;
}
public boolean isDirectJdbcConnection() {
return m_directJdbcConnection;
}
public int getJdbcStatementCacheSize() {
return m_queryCacheSize;
}
public String getJndiName() {
return m_jndiName;
}
public String getJndiInitialContextFactory() {
return m_jndiInitialContextFactory;
}
public String getJndiProviderUrl() {
return m_jndiProviderUrl;
}
public String getJndiUrlPkgPrefixes() {
return m_jndiUrlPkgPrefixes;
}
public String getJdbcMappingName() {
return m_jdbcMappingName;
}
public String getJdbcDriverName() {
return m_jdbcDriverName;
}
public String getJdbcProperties() {
return m_jdbcProps;
}
public String getUsername() {
return m_defaultUser;
}
public String getPassword() {
return m_defaultPass;
}
public int getJdbcPoolSize() {
return m_jdbcPoolSize;
}
public long getJdbcPoolConnectionLifetime() {
return m_jdbcPoolConnectionLifetime;
}
public long getJdbcPoolConnectionBusyTimeout() {
return m_jdbcPoolConnectionBusyTimeout;
}
public int getMaxFetchMemorySize() {
return m_maxFetchMemorySize;
}
public void setTransactionMemberId(String s) {
m_transactionMemberId = s;
}
public void setDirectJdbcConnection(boolean b) {
m_directJdbcConnection = b;
}
public void setJdbcStatementCacheSize(int n) {
m_queryCacheSize = n;
}
public void setJndiName(String s) {
m_jndiName = s;
}
public void setJndiInitialContextFactory(String s) {
m_jndiInitialContextFactory = s;
}
public void setJndiProviderUrl(String s) {
m_jndiProviderUrl = s;
}
public void setJndiUrlPkgPrefixes(String s) {
m_jndiUrlPkgPrefixes = s;
}
/**
* Supports ${...} variables resolved by {@link BundleContextUtility#resolve(String)}
*/
public void setJdbcMappingName(String s) {
m_jdbcMappingName = BundleContextUtility.resolve(s);
}
public void setJdbcDriverName(String s) {
m_jdbcDriverName = s;
}
public void setJdbcProperties(String s) {
m_jdbcProps = s;
}
public void setUsername(String s) {
m_defaultUser = s;
}
public void setPassword(String s) {
m_defaultPass = s;
}
public void setJdbcPoolSize(int n) {
m_jdbcPoolSize = n;
}
public void setJdbcPoolConnectionLifetime(long t) {
m_jdbcPoolConnectionLifetime = t;
}
public void setJdbcPoolConnectionBusyTimeout(long t) {
m_jdbcPoolConnectionBusyTimeout = t;
}
public void setMaxFetchMemorySize(int maxFetchMemorySize) {
m_maxFetchMemorySize = maxFetchMemorySize;
}
@Override
public Object getAdapter(Class adapter) {
if (adapter == IServiceInventory.class) {
if (m_pool != null) {
return m_pool.getInventory();
}
}
return null;
}
public Class<? extends ScoutTexts> getNlsProvider() {
return m_nlsProvider;
}
public void setNlsProvider(Class<? extends ScoutTexts> nlsProvider) {
m_nlsProvider = nlsProvider;
}
@Override
public ISqlStyle getSqlStyle() {
return m_sqlStyle;
}
public void setSqlStyle(ISqlStyle sqlStyle) {
m_sqlStyle = sqlStyle;
}
/*
* Internals
*/
private Connection leaseConnection() throws Throwable {
Connection conn = execCreateConnection();
return conn;
}
private Connection leaseConnectionInternal() throws Throwable {
try {
if (isDirectJdbcConnection()) {
// get connection from internal pool
Connection conn = getSqlConnectionPool().leaseConnection(this);
return conn;
}
else {
Connection conn = new SqlConnectionBuilder().createJndiConnection(this);
// do not call execAfterConnectionCreated(conn) because jndi connections
// are normally pooled
return conn;
}
}
catch (Exception e) {
ProcessingException pe;
if (e instanceof ProcessingException) {
pe = (ProcessingException) e;
}
else {
pe = new ProcessingException("unexpected exception", e);
}
if (isDirectJdbcConnection()) {
pe.addContextMessage("jdbcDriverName=" + getJdbcDriverName() + ", jdbcMappingName=" + getJdbcMappingName());
}
else {
pe.addContextMessage("jndiName=" + getJndiName());
}
throw pe;
}
}
private void releaseConnection(Connection conn) {
try {
execReleaseConnection(conn);
}
catch (Throwable e) {
LOG.error(null, e);
}
}
private void releaseConnectionInternal(Connection conn) throws Throwable {
if (isDirectJdbcConnection()) {
// delegate to internal pool
getSqlConnectionPool().releaseConnection(conn);
}
else {
conn.close();
}
}
private synchronized SqlConnectionPool getSqlConnectionPool() {
if (m_pool == null) {
m_pool = SqlConnectionPool.getPool(getClass(), getJdbcPoolSize(), getJdbcPoolConnectionLifetime(), getJdbcPoolConnectionBusyTimeout());
}
return m_pool;
}
@Override
public Connection getConnection() throws ProcessingException {
return getTransaction();
}
protected Connection getTransaction() throws ProcessingException {
ITransaction reg = ThreadContext.getTransaction();
if (reg == null) {
throw new ProcessingException("no ITransaction available, use ServerJob to run truncactions");
}
SqlTransactionMember member = (SqlTransactionMember) reg.getMember(getTransactionMemberId());
if (member == null) {
Connection conn;
try {
conn = leaseConnection();
member = new SqlTransactionMember(getTransactionMemberId(), conn);
reg.registerMember(member);
// this is the start of the transaction
execBeginTransaction();
}
catch (ProcessingException e) {
throw e;
}
catch (Throwable e) {
throw new ProcessingException("getTransaction", e);
}
}
return member.getConnection();
}
/**
* @return the statement cache used for this {@link ITransaction} transaction
*/
protected final IStatementCache getStatementCache() throws ProcessingException {
ITransaction reg = ThreadContext.getTransaction();
if (reg == null) {
throw new ProcessingException("no ITransaction available, use ServerJob to run truncactions");
}
IStatementCache res = (IStatementCache) reg.getMember(PreparedStatementCache.TRANSACTION_MEMBER_ID);
if (res == null) {
res = new PreparedStatementCache(getJdbcStatementCacheSize());
reg.registerMember((ITransactionMember) res);
}
return res;
}
/*
* Operations
*/
@Override
public Object[][] select(String s, Object... bindBases) throws ProcessingException {
return createStatementProcessor(s, bindBases, 0).processSelect(getTransaction(), getStatementCache(), null);
}
@Override
public Object[][] selectLimited(String s, int maxRowCount, Object... bindBases) throws ProcessingException {
return createStatementProcessor(s, bindBases, maxRowCount).processSelect(getTransaction(), getStatementCache(), null);
}
@Override
public void selectInto(String s, Object... bindBases) throws ProcessingException {
createStatementProcessor(s, bindBases, 0).processSelectInto(getTransaction(), getStatementCache(), null);
}
@Override
public void selectIntoLimited(String s, int maxRowCount, Object... bindBases) throws ProcessingException {
createStatementProcessor(s, bindBases, maxRowCount).processSelectInto(getTransaction(), getStatementCache(), null);
}
@Override
public void selectStreaming(String s, ISelectStreamHandler handler, Object... bindBases) throws ProcessingException {
createStatementProcessor(s, bindBases, 0).processSelectStreaming(getTransaction(), getStatementCache(), handler);
}
@Override
public void selectStreamingLimited(String s, ISelectStreamHandler handler, int maxRowCount, Object... bindBases) throws ProcessingException {
createStatementProcessor(s, bindBases, maxRowCount).processSelectStreaming(getTransaction(), getStatementCache(), handler);
}
@Override
public int insert(String s, Object... bindBases) throws ProcessingException {
return createStatementProcessor(s, bindBases, 0).processModification(getTransaction(), getStatementCache(), null);
}
@Override
public int update(String s, Object... bindBases) throws ProcessingException {
return createStatementProcessor(s, bindBases, 0).processModification(getTransaction(), getStatementCache(), null);
}
@Override
public int delete(String s, Object... bindBases) throws ProcessingException {
return createStatementProcessor(s, bindBases, 0).processModification(getTransaction(), getStatementCache(), null);
}
@Override
public boolean callStoredProcedure(String s, Object... bindBases) throws ProcessingException {
return createStatementProcessor(s, bindBases, 0).processStoredProcedure(getTransaction(), getStatementCache(), null);
}
@Override
public void commit() throws ProcessingException {
try {
getTransaction().commit();
ISqlStyle style = getSqlStyle();
if (style instanceof ISqlStyle2) {
((ISqlStyle2) style).commit();
}
}
catch (SQLException e) {
throw new ProcessingException("unexpected exception", e);
}
}
@Override
public String createPlainText(String s, Object... bindBases) throws ProcessingException {
return createStatementProcessor(s, bindBases, 0).createPlainText();
}
@Override
public WhereToken resolveSpecialConstraint(Object specialConstraint) throws ProcessingException {
if (specialConstraint instanceof LegacySearchFilter.StringLikeConstraint) {
LegacySearchFilter.StringLikeConstraint c = (LegacySearchFilter.StringLikeConstraint) specialConstraint;
String s = getSqlStyle().toLikePattern(c.getValue());
return new LegacySearchFilter.WhereToken(c.getTerm(), s, null);
}
else if (specialConstraint instanceof LegacySearchFilter.ComposerConstraint) {
LegacySearchFilter.ComposerConstraint c = (LegacySearchFilter.ComposerConstraint) specialConstraint;
HashMap<String, Object> map = new HashMap<String, Object>();
String term = c.getTerm();
for (Map.Entry<String, LegacySearchFilter.ComposerAttributeRef> e : c.getAttributeRefMap().entrySet()) {
String key = e.getKey();
LegacySearchFilter.ComposerAttributeRef att = e.getValue();
LegacyStatementBuilder b = new LegacyStatementBuilder(getSqlStyle());
String attValue = b.resolveComposerAttribute(att.getOp(), att.getAttribute(), att.getBindName(), att.getValue());
map.putAll(b.getBindMap());
term = term.replace(key, attValue);
}
return new LegacySearchFilter.WhereToken(term, null, map);
}
return null;
}
protected IStatementProcessor createStatementProcessor(String s, Object[] bindBases, int maxRowCount) throws ProcessingException {
return new StatementProcessor(this, s, bindBases, maxRowCount, m_maxFetchMemorySize);
}
/**
* When the service completes work with an exception, a xa rollback is done on
* ALL used service request resources
*
* @see commit
*/
@Override
public void rollback() throws ProcessingException {
try {
getTransaction().rollback();
ISqlStyle style = getSqlStyle();
if (style instanceof ISqlStyle2) {
((ISqlStyle2) style).rollback();
}
}
catch (SQLException e) {
throw new ProcessingException("unexpected exception", e);
}
}
@Override
public Long getSequenceNextval(String sequenceName) throws ProcessingException {
String s = "SELECT " + sequenceName + ".NEXTVAL FROM DUAL ";
Object[][] ret = createStatementProcessor(s, null, 0).processSelect(getTransaction(), getStatementCache(), null);
if (ret.length == 1) {
return NumberUtility.toLong(NumberUtility.nvl((Number) ret[0][0], 0));
}
return 0L;
}
/**
* @return the class loaded by the first bundle with a matching symbolic name
* Example: name "com.myapp.shared.core.security.ReadDataPermission" is loaded by the bundle with symbolic
* name "com.myapp.shared.core".
*/
private Class loadBundleClassLenient(Map<String, List<BundleClassDescriptor>> map, String name) {
String base = name;
String suffix = "";
while (base.length() > 0) {
List<BundleClassDescriptor> list = map.get(base);
if (list != null) {
for (BundleClassDescriptor desc : list) {
try {
Class c = Platform.getBundle(desc.getBundleSymbolicName()).loadClass(desc.getClassName());
if (suffix.length() > 0) {
c = Platform.getBundle(desc.getBundleSymbolicName()).loadClass(desc.getClassName() + suffix.replace(".", "$"));
return c;
}
else {
return c;
}
}
catch (Throwable t) {
LOG.warn("Could not load class with lenient name '" + name + "' in bundle " + desc.getBundleSymbolicName());
}
}
}
//
int i = base.lastIndexOf('.');
if (i >= 0) {
String seg = base.substring(i);
base = base.substring(0, i);
suffix = seg + suffix;
}
else {
String seg = base;
base = "";
suffix = seg + suffix;
}
}
LOG.warn("Could not find class with lenient name '" + name + "'");
return null;
}
private class SqlTransactionMember extends AbstractSqlTransactionMember {
private final Connection m_conn;
public SqlTransactionMember(String transactionMemberId, Connection conn) {
super(transactionMemberId);
m_conn = conn;
}
public Connection getConnection() {
return m_conn;
}
@Override
public void commitPhase2() {
try {
// this is the end of the transaction
try {
setFinishingTransaction(true);
execEndTransaction(false);
}
finally {
setFinishingTransaction(false);
}
m_conn.commit();
}
catch (Exception e) {
LOG.error(null, e);
}
}
@Override
public void rollback() {
try {
// this is the end of the transaction
try {
setFinishingTransaction(true);
execEndTransaction(false);
}
finally {
setFinishingTransaction(false);
}
m_conn.rollback();
}
catch (Exception e) {
if (!ThreadContext.getTransaction().isCancelled()) {
LOG.error(null, e);
}
}
}
@Override
public void release() {
releaseConnection(m_conn);
}
}// end private class
}