| /** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| package org.apache.tuscany.sdo.impl; |
| |
| |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.tuscany.sdo.SDOFactory; |
| import org.apache.tuscany.sdo.SDOPackage; |
| import org.apache.tuscany.sdo.util.BasicSequence; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.NotificationChain; |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.common.util.BasicEList; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.UniqueEList; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.change.ChangeDescription; |
| import org.eclipse.emf.ecore.change.FeatureChange; |
| import org.eclipse.emf.ecore.change.impl.ChangeDescriptionImpl; |
| import org.eclipse.emf.ecore.change.util.ChangeRecorder; |
| import org.eclipse.emf.ecore.impl.ENotificationImpl; |
| import org.eclipse.emf.ecore.util.BasicExtendedMetaData; |
| import org.eclipse.emf.ecore.util.DelegatingFeatureMap; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.util.FeatureMap; |
| import org.eclipse.emf.ecore.util.FeatureMapUtil; |
| import org.eclipse.emf.ecore.util.InternalEList; |
| |
| import commonj.sdo.ChangeSummary; |
| import commonj.sdo.ChangeSummary.Setting; |
| import commonj.sdo.DataGraph; |
| import commonj.sdo.DataObject; |
| import commonj.sdo.Property; |
| import commonj.sdo.Sequence; |
| |
| |
| /** |
| * <!-- begin-user-doc --> |
| * An implementation of the model object '<em><b>EChange Summary</b></em>'. |
| * <!-- end-user-doc --> |
| * <p> |
| * The following features are implemented: |
| * <ul> |
| * <li>{@link org.apache.tuscany.sdo.impl.ChangeSummaryImpl#getEDataGraph <em>EData Graph</em>}</li> |
| * </ul> |
| * </p> |
| * |
| * @generated |
| */ |
| public class ChangeSummaryImpl extends ChangeDescriptionImpl implements ChangeSummary |
| { |
| /** |
| * The cached value of the '{@link #getEDataGraph() <em>EData Graph</em>}' reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getEDataGraph() |
| * @generated |
| * @ordered |
| */ |
| protected DataGraph eDataGraph; |
| |
| protected DataObject dataObject = null; |
| protected SDOChangeRecorder changeRecorder = null; |
| |
| protected Set cachedDeletedObjects = null; |
| protected List cachedCreatedObjects = null; |
| protected Map cachedSDOObjectChanges = null; |
| protected boolean isStale = false; |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| */ |
| protected ChangeSummaryImpl() |
| { |
| super(); |
| cachedSDOObjectChanges = createThreadSafeMap(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| protected EClass eStaticClass() |
| { |
| return SDOPackage.Literals.CHANGE_SUMMARY; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean isLogging() |
| { |
| return changeRecorder != null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public DataGraph getEDataGraph() |
| { |
| return eDataGraph; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public NotificationChain basicSetEDataGraph(DataGraph newEDataGraph, NotificationChain msgs) |
| { |
| DataGraph oldEDataGraph = eDataGraph; |
| eDataGraph = newEDataGraph; |
| if (eNotificationRequired()) { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH, oldEDataGraph, newEDataGraph); |
| if (msgs == null) msgs = notification; else msgs.add(notification); |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setEDataGraph(DataGraph newEDataGraph) |
| { |
| if (newEDataGraph != eDataGraph) { |
| NotificationChain msgs = null; |
| if (eDataGraph != null) |
| msgs = ((InternalEObject)eDataGraph).eInverseRemove(this, SDOPackage.DATA_GRAPH__ECHANGE_SUMMARY, DataGraph.class, msgs); |
| if (newEDataGraph != null) |
| msgs = ((InternalEObject)newEDataGraph).eInverseAdd(this, SDOPackage.DATA_GRAPH__ECHANGE_SUMMARY, DataGraph.class, msgs); |
| msgs = basicSetEDataGraph(newEDataGraph, msgs); |
| if (msgs != null) msgs.dispatch(); |
| } |
| else if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH, newEDataGraph, newEDataGraph)); |
| } |
| |
| public DataObject getDataObject() |
| { |
| return dataObject; |
| } |
| |
| public void setDataObject(DataObject newDataObject) |
| { |
| dataObject = newDataObject; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void beginLogging() |
| { |
| if (isLogging()) |
| { |
| throw new IllegalStateException("Already logging"); |
| } |
| |
| getObjectsToAttach().clear(); |
| getObjectChanges().clear(); |
| getResourceChanges().clear(); |
| oldContainmentInformation = null; |
| |
| beginRecording(); |
| // if (eNotificationRequired()) |
| // eNotify(new ENotificationImpl(this, Notification.SET, SDOPackage.ECHANGE_SUMMARY__LOGGING, false, true)); |
| } |
| |
| /** |
| * |
| */ |
| private void beginRecording() { |
| changeRecorder = new SDOChangeRecorder(); |
| if (eDataGraph != null) |
| { |
| changeRecorder.beginRecording(Collections.singleton(((DataGraphImpl)eDataGraph).getRootResource())); |
| } |
| else if (dataObject != null) |
| { |
| changeRecorder.beginRecording(Collections.singleton(dataObject)); |
| } |
| else |
| { |
| throw new IllegalStateException("ChangeSummary not attached to any data objects"); |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void resumeLogging() |
| { |
| if (isLogging()) |
| { |
| throw new IllegalStateException("Already logging"); |
| } |
| |
| oldContainmentInformation = null; |
| |
| beginRecording(); |
| // if (eNotificationRequired()) |
| // eNotify(new ENotificationImpl(this, Notification.SET, SDOPackage.ECHANGE_SUMMARY__LOGGING, false, true)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public Object eGet(int featureID, boolean resolve, boolean coreType) |
| { |
| switch (featureID) { |
| case SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH: |
| return getEDataGraph(); |
| } |
| return super.eGet(featureID, resolve, coreType); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void eSet(int featureID, Object newValue) |
| { |
| switch (featureID) { |
| case SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH: |
| setEDataGraph((DataGraph)newValue); |
| return; |
| } |
| super.eSet(featureID, newValue); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void eUnset(int featureID) |
| { |
| switch (featureID) { |
| case SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH: |
| setEDataGraph((DataGraph)null); |
| return; |
| } |
| super.eUnset(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public boolean eIsSet(int featureID) |
| { |
| switch (featureID) { |
| case SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH: |
| return eDataGraph != null; |
| } |
| return super.eIsSet(featureID); |
| } |
| |
| protected void uncache() |
| { |
| cachedDeletedObjects = null; |
| cachedCreatedObjects = null; |
| cachedSDOObjectChanges.clear(); |
| } |
| |
| protected class SDOChangeRecorder extends ChangeRecorder |
| { |
| public SDOChangeRecorder() |
| { |
| super(); |
| } |
| |
| public void beginRecording(ChangeDescription changeDescription, Collection rootObjects) |
| { |
| uncache(); |
| super.beginRecording(changeDescription, rootObjects); |
| } |
| |
| protected ChangeDescription createChangeDescription() |
| { |
| return ChangeSummaryImpl.this; |
| } |
| |
| protected FeatureChange createFeatureChange(EObject eObject, EStructuralFeature eStructuralFeature, Object value, boolean isSet) |
| { |
| Property property = (Property)eStructuralFeature; |
| if (property.isReadOnly()) |
| { |
| if (((DataObject)eObject).getDataGraph() != null) |
| { |
| throw |
| new IllegalStateException |
| ("The property '" + property.getName() + "' of type '" + |
| property.getContainingType().getName() + "' is read only"); |
| } |
| } |
| return (FeatureChange)SDOFactory.eINSTANCE.createChangeSummarySetting(eStructuralFeature, value, isSet); |
| } |
| |
| protected void consolidateChanges() |
| { |
| uncache(); |
| isStale = false; |
| |
| // TODO remove this fixup when https://bugs.eclipse.org/bugs/show_bug.cgi?id=177235 is |
| // available to us (i.e. we update to EMF 2.3) -- see Tuscany-1164 |
| boolean isUncontainedRoot = dataObject != null |
| && ((EObject)dataObject).eContainer() == null |
| && ((EObject)dataObject).eResource() == null; |
| |
| super.consolidateChanges(); |
| |
| if(isUncontainedRoot && changeDescription.getObjectsToAttach().contains(dataObject)) { |
| changeDescription.getObjectsToAttach().remove(dataObject); |
| } |
| |
| } |
| |
| protected void addAdapter(Notifier notifier) |
| { |
| if (!loadingTargets) return; // Optimize ChangeSummary to not record changes in newly created DOs |
| |
| if (notifier instanceof DataObjectImpl) |
| ((DataObjectImpl)notifier).setChangeRecorder(this); |
| else |
| super.addAdapter(notifier); |
| } |
| |
| protected void removeAdapter(Notifier notifier) |
| { |
| if (notifier instanceof DataObjectImpl) |
| ((DataObjectImpl)notifier).setChangeRecorder(null); |
| else |
| super.removeAdapter(notifier); |
| } |
| |
| public void notifyChanged(Notification notification) |
| { |
| super.notifyChanged(notification); |
| |
| Object notifier = notification.getNotifier(); |
| if (notifier instanceof EObject) |
| { |
| cachedSDOObjectChanges.remove(notifier); |
| Object feature = notification.getFeature(); |
| if (feature instanceof Property && ((Property)feature).isContainment()) |
| { |
| cachedCreatedObjects = null; |
| cachedDeletedObjects = null; |
| oldContainmentInformation = null; |
| } |
| isStale = true; |
| } |
| } |
| |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void endLogging() |
| { |
| if (!isLogging()) |
| { |
| throw new IllegalStateException("Not currently logging"); |
| } |
| |
| changeRecorder.endRecording(); |
| changeRecorder.dispose(); |
| changeRecorder = null; |
| // if (eNotificationRequired()) |
| // eNotify(new ENotificationImpl(this, Notification.SET, SDOPackage.ECHANGE_SUMMARY__LOGGING, true, false)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean isCreated(DataObject dataObject) |
| { |
| return getCachedCreatedObjects().contains(dataObject); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean isDeleted(DataObject dataObject) |
| { |
| return getCachedDeletedObjects().contains(dataObject); |
| } |
| |
| protected Set getCachedDeletedObjects() |
| { |
| if (cachedDeletedObjects == null) |
| { |
| if (isStale()) changeRecorder.consolidateChanges(); |
| cachedDeletedObjects = new HashSet(); |
| for (Iterator i = EcoreUtil.getAllContents(getObjectsToAttach()); i.hasNext(); ) |
| { |
| cachedDeletedObjects.add(i.next()); |
| } |
| } |
| return cachedDeletedObjects; |
| } |
| |
| protected List getCachedCreatedObjects() |
| { |
| if (cachedCreatedObjects == null) |
| { |
| if (isStale()) changeRecorder.consolidateChanges(); |
| cachedCreatedObjects = super.getObjectsToDetach(); |
| } |
| return cachedCreatedObjects; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public List getChangedDataObjects() |
| { |
| EList result = new UniqueEList.FastCompare(getCachedDeletedObjects()); |
| result.addAll(getCachedCreatedObjects()); |
| for (Iterator i = getObjectChanges().iterator(); i.hasNext(); ) |
| { |
| Map.Entry entry = (Map.Entry)i.next(); |
| result.add(entry.getKey()); |
| } |
| return result; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public List getOldValues(DataObject dataObject) |
| { |
| List sdoSettings = (List)cachedSDOObjectChanges.get(dataObject); |
| if (sdoSettings != null) |
| { |
| return sdoSettings; |
| } |
| |
| if (isStale()) changeRecorder.consolidateChanges(); |
| List settings = (List)getObjectChanges().get(dataObject); |
| if (settings == null) |
| { |
| settings = Collections.EMPTY_LIST; |
| } |
| else |
| { |
| for (int i = 0; i < settings.size(); i++) |
| { |
| FeatureChange change = (FeatureChange)settings.get(i); |
| EStructuralFeature feature = change.getFeature(); |
| if (FeatureMapUtil.isFeatureMap(feature)) |
| { |
| final List values = (List)change.getValue(); |
| if (sdoSettings == null) |
| { |
| sdoSettings = new BasicEList(settings); |
| } |
| DelegatingFeatureMap featureMap = new DelegatingFeatureMap(((InternalEObject)dataObject), feature) |
| { |
| protected final List theList = values; |
| |
| protected List delegateList() |
| { |
| return theList; |
| } |
| }; |
| |
| // create new settings and replace the setting for mixed feature |
| sdoSettings.set(i, SDOFactory.eINSTANCE.createChangeSummarySetting(feature, new BasicSequence(featureMap), change.isSet())); |
| // add all derived features |
| for (int k = 0; k < featureMap.size(); k++) |
| { |
| EStructuralFeature f = featureMap.getEStructuralFeature(k); |
| sdoSettings.add(SDOFactory.eINSTANCE.createChangeSummarySetting(f, featureMap.get(f, false), true)); |
| } |
| } |
| } |
| } |
| sdoSettings = (sdoSettings != null) ? sdoSettings : settings; |
| cachedSDOObjectChanges.put(dataObject, sdoSettings); |
| return sdoSettings; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean isModified(DataObject dataObject) |
| { |
| return getObjectChanges().containsKey(dataObject) && !isDeleted(dataObject) && !isCreated(dataObject); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void summarize() |
| { |
| if (!isLogging()) |
| { |
| throw new IllegalStateException("Not currently logging"); |
| } |
| |
| changeRecorder.summarize(); |
| } |
| |
| public Setting getOldValue(DataObject dataObject, Property property) |
| { |
| for (Iterator i = getOldValues(dataObject).iterator(); i.hasNext(); ) |
| { |
| Setting setting = (Setting)i.next(); |
| if (setting.getProperty() == property) |
| { |
| return setting; |
| } |
| } |
| |
| return null; |
| } |
| |
| public DataObject getOldContainer(DataObject dataObject) |
| { |
| return (DataObject)getOldContainer((EObject)dataObject); |
| } |
| |
| public Property getOldContainmentProperty(DataObject dataObject) |
| { |
| return (Property)getOldContainmentFeature((EObject)dataObject); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public Sequence getOldSequence(DataObject dataObject) |
| { |
| EAttribute mixedFeature = BasicExtendedMetaData.INSTANCE.getMixedFeature((EClass)dataObject.getType()); |
| if (mixedFeature != null) |
| { |
| return (Sequence)getOldValue(dataObject, (Property)mixedFeature).getValue(); |
| } |
| return null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void undoChanges() |
| { |
| if (isLogging()) |
| { |
| changeRecorder.summarize(); |
| } |
| else |
| { |
| uncache(); |
| } |
| apply(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public DataGraph getDataGraph() |
| { |
| return getEDataGraph(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public List getChangedObjects() { |
| // TODO: implement this method |
| // Ensure that you remove @generated or mark it @generated NOT |
| throw new UnsupportedOperationException(); |
| } |
| |
| protected Map getOldContainmentInformation() |
| { |
| if (oldContainmentInformation == null) |
| { |
| if (isStale()) changeRecorder.consolidateChanges(); |
| super.getOldContainmentInformation(); |
| } |
| return oldContainmentInformation; |
| } |
| |
| protected boolean isStale() |
| { |
| return isLogging() && isStale; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public DataObject getRootObject() |
| { |
| if (eDataGraph != null) |
| { |
| return eDataGraph.getRootObject(); |
| } |
| if (dataObject != null) |
| { |
| return dataObject; |
| } |
| return null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) { |
| switch (featureID) { |
| case SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH: |
| if (eDataGraph != null) |
| msgs = ((InternalEObject)eDataGraph).eInverseRemove(this, SDOPackage.DATA_GRAPH__ECHANGE_SUMMARY, DataGraph.class, msgs); |
| return basicSetEDataGraph((DataGraph)otherEnd, msgs); |
| } |
| return super.eInverseAdd(otherEnd, featureID, msgs); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { |
| switch (featureID) { |
| case SDOPackage.CHANGE_SUMMARY__EDATA_GRAPH: |
| return basicSetEDataGraph(null, msgs); |
| } |
| return super.eInverseRemove(otherEnd, featureID, msgs); |
| } |
| |
| static protected boolean isContainmentReference(Object feature) |
| { |
| return feature instanceof EReference && ((EReference) feature).isContainment(); |
| } |
| |
| public DataObject getOldDataObject(DataObject dataObject) |
| { |
| //TODO: Fix this method. Currently, it has the side effect of undoing the unset of contained children references |
| // of root deleted objects - i.e., when featureChange.apply(oldDataObject) is called. |
| // |
| List changes = (List) getObjectChanges().get(dataObject); |
| if (changes == null) |
| return dataObject; |
| EObject oldDataObject = EcoreUtil.copy((EObject)dataObject); |
| for (Iterator fIter = changes.iterator(); fIter.hasNext(); ) |
| { |
| FeatureChange featureChange = (FeatureChange)fIter.next(); |
| featureChange.apply(oldDataObject); |
| EStructuralFeature feature = featureChange.getFeature(); |
| if (FeatureMapUtil.isFeatureMap(feature)) |
| { |
| FeatureMap featureMap = (FeatureMap) oldDataObject.eGet(feature); |
| for (int index = featureMap.size(); index != 0;) |
| if (isContainmentReference(featureMap.getEStructuralFeature(--index))) |
| featureMap.setValue(index, getOldDataObject((DataObject) featureMap.getValue(index))); |
| } |
| else if (isContainmentReference(feature)) |
| { |
| Object value = oldDataObject.eGet(feature); |
| if (feature.isMany()) |
| { |
| changes = (List) value; |
| for (int index = changes.size(); index != 0;) |
| changes.set(--index, getOldDataObject((DataObject) changes.get(index))); // Java pushes stack from left to right |
| } |
| else |
| oldDataObject.eSet(feature, getOldDataObject((DataObject) value)); |
| } |
| } |
| |
| return (DataObject)oldDataObject; |
| } |
| |
| private static Class concurrentHashMapClazz = null; |
| private static boolean isThreadSafeMapClazzIdentified = false; |
| |
| private Map createThreadSafeMap() |
| { |
| if (!isThreadSafeMapClazzIdentified) |
| { |
| concurrentHashMapClazz = loadConcurrentHashMapClazz(); |
| isThreadSafeMapClazzIdentified = true; |
| } |
| Map threadSafeMap = null; |
| if (concurrentHashMapClazz == null) |
| { |
| threadSafeMap = Collections.synchronizedMap(new HashMap()); |
| } |
| else |
| { |
| try |
| { |
| threadSafeMap = (Map)concurrentHashMapClazz.newInstance(); |
| } |
| catch (InstantiationException e) |
| { |
| throw new RuntimeException(e); |
| } |
| catch (IllegalAccessException e) |
| { |
| throw new RuntimeException(e); |
| } |
| } |
| return threadSafeMap; |
| } |
| |
| private static String[] concurrentHashMapClazzNames = new String[] { |
| "java.util.concurrent.ConcurrentHashMap", |
| "edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap"}; |
| |
| private static Class loadConcurrentHashMapClazz() |
| { |
| Class mapClazz = null; |
| for (int i = 0; i < concurrentHashMapClazzNames.length; i++) |
| { |
| String concurrentHashMapClazzName = concurrentHashMapClazzNames[i]; |
| try |
| { |
| mapClazz = Class.forName(concurrentHashMapClazzName, true, Thread.currentThread().getContextClassLoader()); |
| } |
| catch (Exception ignored) {} |
| if (mapClazz != null) |
| { |
| break; |
| } |
| try |
| { |
| mapClazz = Class.forName(concurrentHashMapClazzName); |
| } |
| catch (Exception ignored) {} |
| if (mapClazz != null) |
| { |
| break; |
| } |
| } |
| return mapClazz; |
| } |
| |
| } //ChangeSummaryImpl |